diff --git a/include/user.h b/include/user.h index 00cd9ae311d..8e6c5e21aeb 100644 --- a/include/user.h +++ b/include/user.h @@ -31,6 +31,7 @@ extern WORD USER_HeapSel; void WINAPI USER_SignalProc(HANDLE16, UINT16, UINT16, HINSTANCE16, HQUEUE16); void USER_ExitWindows(void); +void USER_QueueCleanup( HQUEUE16 hQueue ); HGLOBAL16 USER_CallDefaultRsrcHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc ); diff --git a/scheduler/thread.c b/scheduler/thread.c index b68a3f6b198..0cd707f31fb 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -335,6 +335,10 @@ void WINAPI ExitThread( SYSTEM_LOCK(); thdb->exit_code = code; + /* cleanup the message queue, if there's one */ + if (thdb->teb.queue) + USER_QueueCleanup( thdb->teb.queue ); + /* FIXME: should free the stack somehow */ #if 0 /* FIXME: We cannot do this; once the current thread is destroyed, diff --git a/windows/queue.c b/windows/queue.c index fcaff9763e4..9195e2776cc 100644 --- a/windows/queue.c +++ b/windows/queue.c @@ -512,9 +512,18 @@ BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue ) while (*pPrev && (*pPrev != hQueue)) { MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock16(*pPrev); + + /* sanity check */ + if ( !msgQ || (msgQ->magic != QUEUE_MAGIC) ) + { + /* HQUEUE link list is corrupted, try to exit gracefully */ + WARN( msg, "HQUEUE link list corrupted!\n"); + pPrev = 0; + break; + } pPrev = &msgQ->next; } - if (*pPrev) *pPrev = msgQueue->next; + if (pPrev && *pPrev) *pPrev = msgQueue->next; msgQueue->self = 0; SYSTEM_UNLOCK(); @@ -579,7 +588,7 @@ static void QUEUE_Wait( DWORD wait_mask ) /*********************************************************************** - * QUEUE_SetWakeBit ` + * QUEUE_SetWakeBit * * See "Windows Internals", p.449 */ diff --git a/windows/user.c b/windows/user.c index d8241b87c34..8a709033020 100644 --- a/windows/user.c +++ b/windows/user.c @@ -161,22 +161,14 @@ static void USER_ModuleUnload( HMODULE16 hModule ) } /********************************************************************** - * USER_AppExit + * USER_QueueCleanup */ -static void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue ) +void USER_QueueCleanup( HQUEUE16 hQueue ) { if ( hQueue ) { - /* FIXME: empty clipboard if needed, maybe destroy menus (Windows - * only complains about them but does nothing); - */ - WND* desktop = WIN_GetDesktop(); - /* Patch desktop window */ - if( desktop->hmemTaskQ == hQueue ) - desktop->hmemTaskQ = GetTaskQueue(TASK_GetNextTask(hTask)); - /* Patch resident popup menu window */ MENU_PatchResidentPopup( hQueue, NULL ); @@ -193,6 +185,24 @@ static void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue /* Free the message queue */ QUEUE_DeleteMsgQueue( hQueue ); } +} + +/********************************************************************** + * USER_AppExit + */ +static void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue ) +{ + /* FIXME: empty clipboard if needed, maybe destroy menus (Windows + * only complains about them but does nothing); + */ + + WND* desktop = WIN_GetDesktop(); + + /* Patch desktop window */ + if( desktop->hmemTaskQ == hQueue ) + desktop->hmemTaskQ = GetTaskQueue(TASK_GetNextTask(hTask)); + + USER_QueueCleanup(hQueue); /* ModuleUnload() in "Internals" */