From f2992e0c096333ecc7b5235ce65293e048c62673 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Sat, 22 May 2004 21:12:15 +0000 Subject: [PATCH] prevent memory leaks if callbacks to usermode never return svn path=/trunk/; revision=9473 --- reactos/include/napi/win32.h | 2 + reactos/subsys/win32k/include/callback.h | 12 ++- reactos/subsys/win32k/include/tags.h | 1 + reactos/subsys/win32k/main/dllmain.c | 5 +- reactos/subsys/win32k/ntuser/callback.c | 112 +++++++++++++++++------ reactos/subsys/win32k/ntuser/message.c | 4 +- reactos/subsys/win32k/ntuser/winsta.c | 6 +- 7 files changed, 103 insertions(+), 39 deletions(-) diff --git a/reactos/include/napi/win32.h b/reactos/include/napi/win32.h index 7c323b65417..e3c6e53e021 100644 --- a/reactos/include/napi/win32.h +++ b/reactos/include/napi/win32.h @@ -8,6 +8,8 @@ typedef struct _W32THREAD PVOID MessageQueue; FAST_MUTEX WindowListLock; LIST_ENTRY WindowListHead; + FAST_MUTEX W32CallbackListLock; + LIST_ENTRY W32CallbackListHead; struct _KBDTABLES* KeyboardLayout; struct _DESKTOP_OBJECT* Desktop; HANDLE hDesktop; diff --git a/reactos/subsys/win32k/include/callback.h b/reactos/subsys/win32k/include/callback.h index b0ab227baf1..d8194a77440 100644 --- a/reactos/subsys/win32k/include/callback.h +++ b/reactos/subsys/win32k/include/callback.h @@ -21,9 +21,6 @@ IntCallSentMessageCallback(SENDASYNCPROC CompletionCallback, HMENU STDCALL IntLoadSysMenuTemplate(); -BOOL STDCALL -IntLoadDefaultCursors(BOOL SetDefault); - LRESULT STDCALL IntCallHookProc(INT HookId, INT Code, @@ -33,4 +30,13 @@ IntCallHookProc(INT HookId, BOOLEAN Ansi, PUNICODE_STRING ModuleName); +VOID FASTCALL +IntCleanupThreadCallbacks(PW32THREAD W32Thread); + +PVOID FASTCALL +IntCbAllocateMemory(ULONG Size); + +VOID FASTCALL +IntCbFreeMemory(PVOID Data); + #endif /* _WIN32K_CALLBACK_H */ diff --git a/reactos/subsys/win32k/include/tags.h b/reactos/subsys/win32k/include/tags.h index 9ce0a959d69..83dfc2b19fa 100644 --- a/reactos/subsys/win32k/include/tags.h +++ b/reactos/subsys/win32k/include/tags.h @@ -21,6 +21,7 @@ #define TAG_TIMER TAG('T', 'I', 'M', 'R') /* timer entry */ #define TAG_TIMERTD TAG('T', 'I', 'M', 'T') /* timer thread dereference list */ #define TAG_TIMERBMP TAG('T', 'I', 'M', 'B') /* timers bitmap */ +#define TAG_CALLBACK TAG('C', 'B', 'C', 'K') /* callback memory */ /* objects */ #define TAG_BEZIER TAG('B', 'E', 'Z', 'R') /* bezier */ diff --git a/reactos/subsys/win32k/main/dllmain.c b/reactos/subsys/win32k/main/dllmain.c index 42e9fec7eb9..ce8063a5ed0 100644 --- a/reactos/subsys/win32k/main/dllmain.c +++ b/reactos/subsys/win32k/main/dllmain.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dllmain.c,v 1.75 2004/05/22 16:48:50 weiden Exp $ +/* $Id: dllmain.c,v 1.76 2004/05/22 21:12:15 weiden Exp $ * * Entry Point for win32k.sys */ @@ -149,6 +149,8 @@ Win32kThreadCallback (struct _ETHREAD *Thread, Win32Thread->MessagePumpHookValue = 0; InitializeListHead(&Win32Thread->WindowListHead); ExInitializeFastMutex(&Win32Thread->WindowListLock); + InitializeListHead(&Win32Thread->W32CallbackListHead); + ExInitializeFastMutex(&Win32Thread->W32CallbackListLock); /* By default threads get assigned their process's desktop. */ Win32Thread->Desktop = NULL; @@ -182,6 +184,7 @@ Win32kThreadCallback (struct _ETHREAD *Thread, DestroyThreadWindows(Thread); IntBlockInput(Win32Thread, FALSE); MsqDestroyMessageQueue(Win32Thread->MessageQueue); + IntCleanupThreadCallbacks(Win32Thread); } return STATUS_SUCCESS; diff --git a/reactos/subsys/win32k/ntuser/callback.c b/reactos/subsys/win32k/ntuser/callback.c index a3f3cd5ac4a..3b254fc87c5 100644 --- a/reactos/subsys/win32k/ntuser/callback.c +++ b/reactos/subsys/win32k/ntuser/callback.c @@ -16,15 +16,19 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: callback.c,v 1.22 2004/05/10 17:07:18 weiden Exp $ +/* $Id: callback.c,v 1.23 2004/05/22 21:12:15 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Window classes * FILE: subsys/win32k/ntuser/wndproc.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * Thomas Weidenmueller (w3seek@users.sourceforge.net) * REVISION HISTORY: * 06-06-2001 CSH Created + * NOTES: Please use the Callback Memory Management functions for + * callbacks to make sure, the memory is freed on thread + * termination! */ /* INCLUDES ******************************************************************/ @@ -34,7 +38,78 @@ #define NDEBUG #include -#define TAG_CALLBACK TAG('C', 'B', 'C', 'K') +/* CALLBACK MEMORY MANAGEMENT ************************************************/ + +typedef struct _INT_CALLBACK_HEADER +{ + /* list entry in the W32THREAD structure */ + LIST_ENTRY ListEntry; +} INT_CALLBACK_HEADER, *PINT_CALLBACK_HEADER; + +PVOID FASTCALL +IntCbAllocateMemory(ULONG Size) +{ + PINT_CALLBACK_HEADER Mem; + PW32THREAD W32Thread; + + if(!(Mem = ExAllocatePoolWithTag(PagedPool, Size + sizeof(INT_CALLBACK_HEADER), + TAG_CALLBACK))) + { + return NULL; + } + + W32Thread = PsGetWin32Thread(); + ASSERT(W32Thread); + + /* insert the callback memory into the thread's callback list */ + + ExAcquireFastMutex(&W32Thread->W32CallbackListLock); + InsertTailList(&W32Thread->W32CallbackListHead, &Mem->ListEntry); + ExReleaseFastMutex(&W32Thread->W32CallbackListLock); + + return (Mem + 1); +} + +VOID FASTCALL +IntCbFreeMemory(PVOID Data) +{ + PINT_CALLBACK_HEADER Mem; + PW32THREAD W32Thread; + + ASSERT(Data); + + Mem = ((PINT_CALLBACK_HEADER)Data - 1); + + W32Thread = PsGetWin32Thread(); + ASSERT(W32Thread); + + /* remove the memory block from the thread's callback list */ + ExAcquireFastMutex(&W32Thread->W32CallbackListLock); + RemoveEntryList(&Mem->ListEntry); + ExReleaseFastMutex(&W32Thread->W32CallbackListLock); + + /* free memory */ + ExFreePool(Mem); +} + +VOID FASTCALL +IntCleanupThreadCallbacks(PW32THREAD W32Thread) +{ + PLIST_ENTRY CurrentEntry; + PINT_CALLBACK_HEADER Mem; + + ExAcquireFastMutex(&W32Thread->W32CallbackListLock); + while (!IsListEmpty(&W32Thread->W32CallbackListHead)) + { + CurrentEntry = RemoveHeadList(&W32Thread->W32CallbackListHead); + Mem = CONTAINING_RECORD(CurrentEntry, INT_CALLBACK_HEADER, + ListEntry); + + /* free memory */ + ExFreePool(Mem); + } + ExReleaseFastMutex(&W32Thread->W32CallbackListLock); +} /* FUNCTIONS *****************************************************************/ @@ -85,7 +160,7 @@ IntCallWindowProc(WNDPROC Proc, if (0 < lParamBufferSize) { ArgumentLength = sizeof(WINDOWPROC_CALLBACK_ARGUMENTS) + lParamBufferSize; - Arguments = ExAllocatePoolWithTag(PagedPool,ArgumentLength, TAG_CALLBACK); + Arguments = IntCbAllocateMemory(ArgumentLength); if (NULL == Arguments) { DPRINT1("Unable to allocate buffer for window proc callback\n"); @@ -117,7 +192,7 @@ IntCallWindowProc(WNDPROC Proc, { if (0 < lParamBufferSize) { - ExFreePool(Arguments); + IntCbFreeMemory(Arguments); } return -1; } @@ -128,7 +203,7 @@ IntCallWindowProc(WNDPROC Proc, RtlMoveMemory((PVOID) lParam, (PVOID) ((char *) Arguments + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)), lParamBufferSize); - ExFreePool(Arguments); + IntCbFreeMemory(Arguments); } return Result; @@ -156,28 +231,6 @@ IntLoadSysMenuTemplate() return (HMENU)Result; } -BOOL STDCALL -IntLoadDefaultCursors(BOOL SetDefault) -{ - LRESULT Result; - NTSTATUS Status; - PVOID ResultPointer; - ULONG ResultLength; - - ResultPointer = &Result; - ResultLength = sizeof(LRESULT); - Status = NtW32Call(USER32_CALLBACK_LOADDEFAULTCURSORS, - &SetDefault, - sizeof(BOOL), - &ResultPointer, - &ResultLength); - if (!NT_SUCCESS(Status)) - { - return(0); - } - return (BOOL)Result; -} - LRESULT STDCALL IntCallHookProc(INT HookId, INT Code, @@ -229,7 +282,7 @@ IntCallHookProc(INT HookId, return 0; } - Argument = ExAllocatePoolWithTag(PagedPool, ArgumentLength, TAG_CALLBACK); + Argument = IntCbAllocateMemory(ArgumentLength); if (NULL == Argument) { DPRINT1("HookProc callback failed: out of memory\n"); @@ -283,6 +336,9 @@ IntCallHookProc(INT HookId, ArgumentLength, &ResultPointer, &ResultLength); + + IntCbFreeMemory(Argument); + if (!NT_SUCCESS(Status)) { return 0; diff --git a/reactos/subsys/win32k/ntuser/message.c b/reactos/subsys/win32k/ntuser/message.c index 66fb98ad808..42cc2eec8b5 100644 --- a/reactos/subsys/win32k/ntuser/message.c +++ b/reactos/subsys/win32k/ntuser/message.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: message.c,v 1.68 2004/05/22 09:22:41 weiden Exp $ +/* $Id: message.c,v 1.69 2004/05/22 21:12:15 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -410,8 +410,6 @@ IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg, USHORT *Hit if(!(Window = IntGetWindowObject(Msg->hwnd))) { - /* FIXME - change the mouse cursor to an arrow, maybe do this a better way */ - IntLoadDefaultCursors(TRUE); /* let's just eat the message?! */ return TRUE; } diff --git a/reactos/subsys/win32k/ntuser/winsta.c b/reactos/subsys/win32k/ntuser/winsta.c index 66e21c5ae48..ed330d0af00 100644 --- a/reactos/subsys/win32k/ntuser/winsta.c +++ b/reactos/subsys/win32k/ntuser/winsta.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: winsta.c,v 1.62 2004/05/15 23:07:11 weiden Exp $ + * $Id: winsta.c,v 1.63 2004/05/22 21:12:15 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -198,9 +198,7 @@ IntInitializeDesktopGraphics(VOID) DC_SetOwnership(ScreenDeviceContext, NULL); EnableMouse(ScreenDeviceContext); - - /* not the best place to load the cursors but it's good for now */ - IntLoadDefaultCursors(FALSE); + NtUserAcquireOrReleaseInputOwnership(FALSE); return TRUE;