diff --git a/Contrib/System/Source/Buffers.c b/Contrib/System/Source/Buffers.c index 00e055d6..fc9ea664 100644 --- a/Contrib/System/Source/Buffers.c +++ b/Contrib/System/Source/Buffers.c @@ -56,12 +56,6 @@ PLUGINFUNCTIONSHORT(Copy) } PLUGINFUNCTIONEND -PLUGINFUNCTIONSHORT(Free) -{ - GlobalFree((HANDLE) popint64()); -} -PLUGINFUNCTIONEND - PLUGINFUNCTION(Store) { TempStack *tmp; diff --git a/Contrib/System/Source/System.c b/Contrib/System/Source/System.c index c6182f15..8fb1146d 100644 --- a/Contrib/System/Source/System.c +++ b/Contrib/System/Source/System.c @@ -42,6 +42,7 @@ int LastStackReal; DWORD LastError; volatile SystemProc *LastProc; int CallbackIndex; +CallbackThunk* CallbackThunkListHead; HINSTANCE g_hInstance; // Return to callback caller with stack restore @@ -136,6 +137,36 @@ PLUGINFUNCTION(Debug) #endif +PLUGINFUNCTIONSHORT(Free) +{ + HANDLE memtofree = (HANDLE)popint64(); + + if (CallbackThunkListHead) + { + CallbackThunk *pCb=CallbackThunkListHead,*pPrev=NULL; + do + { + if (GetAssociatedSysProcFromCallbackThunkPtr(pCb) == (SystemProc*)memtofree) + { + if (pPrev) + pPrev->pNext=pCb->pNext; + else + CallbackThunkListHead=pCb->pNext; + + --(CallbackIndex); + VirtualFree(pCb,0,MEM_RELEASE); + break; + } + pPrev=pCb; + pCb=pCb->pNext; + } + while( pCb != NULL ); + } + + GlobalFree(memtofree); +} +PLUGINFUNCTIONEND + PLUGINFUNCTION(Get) { SystemProc *proc = PrepareProc(FALSE); @@ -917,13 +948,22 @@ HANDLE CreateCallback(SystemProc *cbproc) cbproc->CallbackIndex = ++(CallbackIndex); cbproc->Options |= POPT_PERMANENT; - mem = (char *) (cbproc->Proc = VirtualAlloc(NULL, 10, MEM_COMMIT, PAGE_EXECUTE_READWRITE)); + mem = (char *) (cbproc->Proc = VirtualAlloc(NULL, sizeof(CallbackThunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE)); + + ((CallbackThunk*)mem)->pNext=CallbackThunkListHead; + CallbackThunkListHead=(CallbackThunk*)mem; + +#ifdef SYSTEM_X86 *(mem++) = (char) 0xB8; // Mov eax, const *((int *)mem) = (int) cbproc; mem += sizeof(int); *(mem++) = (char) 0xe9; // Jmp relative *((int *)mem) = (int) RealCallBack; *((int *)mem) -= ((int) mem) + 4; +#else +#error "Asm thunk not implemeted for this architecture!" +#endif + } // Return proc address @@ -1043,6 +1083,7 @@ BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) LastError = 0; LastProc = NULL; CallbackIndex = 0; + CallbackThunkListHead = NULL; retexpr[0] = (char) 0xC2; retexpr[2] = 0x00; } diff --git a/Contrib/System/Source/System.h b/Contrib/System/Source/System.h index fa4ea8ef..e07d426a 100644 --- a/Contrib/System/Source/System.h +++ b/Contrib/System/Source/System.h @@ -101,6 +101,34 @@ struct tag_SystemProc SystemProc *Clone; }; +typedef struct tag_CallbackThunk CallbackThunk; +struct tag_CallbackThunk +{ + #ifdef SYSTEM_X86 + /* + #pragma pack(push,1) + char mov_eax_imm; + int sysprocptr; + char reljmp_imm; + int realprocaddr; + #pragma pack(pop) + */ + char asm[10]; + #else + #error "Asm thunk not implemeted for this architecture!" + #endif + + CallbackThunk* pNext; +}; + +// Free() only knows about pNext in CallbackThunk, it does not know anything about the assembly, that is where this helper comes in... +#ifdef SYSTEM_X86 +# define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) ( (SystemProc*) *(unsigned int*) (((char*)(pCbT))+1) ) +#else +# error "GetAssociatedSysProcFromCallbackThunkPtr not defined for the current architecture!" +#endif + + extern const int ParamSizeByType[]; // Size of every parameter type (*4 bytes) extern HANDLE CreateCallback(SystemProc *cbproc);