prevent memory leaks if callbacks to usermode never return

svn path=/trunk/; revision=9473
This commit is contained in:
Thomas Bluemel 2004-05-22 21:12:15 +00:00
parent ef7b36dd46
commit f2992e0c09
7 changed files with 103 additions and 39 deletions

View file

@ -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;

View file

@ -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 */

View file

@ -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 */

View file

@ -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;

View file

@ -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 <debug.h>
#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;

View file

@ -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;
}

View file

@ -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;