1. don't dispatch sent messages to windows during destruction

2. fixed class lookup in a hacky way (get's rewritten soon anyway)

svn path=/trunk/; revision=12026
This commit is contained in:
Thomas Bluemel
2004-12-11 19:39:18 +00:00
parent 38520a606d
commit ed47eaa79a
7 changed files with 157 additions and 61 deletions
+1
View File
@@ -27,6 +27,7 @@ typedef struct _WNDCLASS_OBJECT
BOOL Unicode;
BOOL Global;
LIST_ENTRY ListEntry;
LIST_ENTRY GlobalListEntry; /* HACK!!! */
PCHAR ExtraData;
/* list of windows */
FAST_MUTEX ClassWindowsListLock;
+1
View File
@@ -203,6 +203,7 @@ VOID FASTCALL MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks);
LPARAM FASTCALL MsqSetMessageExtraInfo(LPARAM lParam);
LPARAM FASTCALL MsqGetMessageExtraInfo(VOID);
VOID STDCALL MsqRemoveWindowMessagesFromQueue(PVOID pWindow); /* F*(&$ headers, will be gone in the rewrite! */
#define IntLockMessageQueue(MsgQueue) \
ExAcquireFastMutex(&(MsgQueue)->Lock)
+32 -11
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: class.c,v 1.60 2004/11/20 16:46:06 weiden Exp $
/* $Id: class.c,v 1.61 2004/12/11 19:39:18 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -33,11 +33,22 @@
#define NDEBUG
#include <debug.h>
/* FIXME: Just a bad hack for now... */
LIST_ENTRY GlobalClassListHead;
FAST_MUTEX GlobalClassListLock;
#define IntLockGlobalClassList() \
ExAcquireFastMutex(&GlobalClassListLock)
#define IntUnlockGlobalClassList() \
ExReleaseFastMutex(&GlobalClassListLock)
/* FUNCTIONS *****************************************************************/
NTSTATUS FASTCALL
InitClassImpl(VOID)
{
ExInitializeFastMutex(&GlobalClassListLock);
InitializeListHead(&GlobalClassListHead);
return(STATUS_SUCCESS);
}
@@ -55,19 +66,19 @@ ClassReferenceClassByAtom(
{
PWNDCLASS_OBJECT Current, BestMatch = NULL;
PLIST_ENTRY CurrentEntry;
PW32PROCESS Process = PsGetWin32Process();
IntLockProcessClasses(Process);
CurrentEntry = Process->ClassListHead.Flink;
while (CurrentEntry != &Process->ClassListHead)
/* HACK!! */
IntLockGlobalClassList();
CurrentEntry = GlobalClassListHead.Flink;
while (CurrentEntry != &GlobalClassListHead)
{
Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, GlobalListEntry);
if (Current->Atom == Atom && (hInstance == NULL || Current->hInstance == hInstance))
{
*Class = Current;
ObmReferenceObject(Current);
IntUnLockProcessClasses(Process);
IntUnlockGlobalClassList();
return TRUE;
}
@@ -76,7 +87,7 @@ ClassReferenceClassByAtom(
CurrentEntry = CurrentEntry->Flink;
}
IntUnLockProcessClasses(Process);
IntUnlockGlobalClassList();
if (BestMatch != NULL)
{
@@ -111,6 +122,7 @@ ClassReferenceClassByName(
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to lookup class atom!\n");
return FALSE;
}
@@ -413,16 +425,16 @@ NtUserRegisterClassExWOW(
WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
if (ClassName->Length)
if (ClassName->Length > 0)
{
DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
DPRINT1("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
/* FIXME - Safely copy/verify the buffer first!!! */
Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
ClassName->Buffer,
&Atom);
if (!NT_SUCCESS(Status))
{
DPRINT("Failed adding class name (%S) to atom table\n",
DPRINT1("Failed adding class name (%S) to atom table\n",
ClassName->Buffer);
SetLastNtError(Status);
return((RTL_ATOM)0);
@@ -445,6 +457,11 @@ NtUserRegisterClassExWOW(
IntLockProcessClasses(PsGetWin32Process());
InsertTailList(&PsGetWin32Process()->ClassListHead, &ClassObject->ListEntry);
IntUnLockProcessClasses(PsGetWin32Process());
/* HACK!!! */
IntLockGlobalClassList();
InsertTailList(&GlobalClassListHead, &ClassObject->GlobalListEntry);
IntUnlockGlobalClassList();
return(Atom);
}
@@ -681,6 +698,10 @@ NtUserUnregisterClass(
ClassDereferenceObject(Class);
RemoveEntryList(&Class->ListEntry);
IntLockGlobalClassList();
RemoveEntryList(&Class->GlobalListEntry);
IntUnlockGlobalClassList();
RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Class->Atom);
+20 -2
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.75 2004/11/20 16:46:06 weiden Exp $
/* $Id: message.c,v 1.76 2004/12/11 19:39:18 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -519,7 +519,10 @@ IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg, USHORT *Hit
{
/* post the message to the other window */
Msg->hwnd = Wnd->Self;
MsqPostMessage(Wnd->MessageQueue, Msg, FALSE);
if(!(Wnd->Status & WINDOWSTATUS_DESTROYING))
{
MsqPostMessage(Wnd->MessageQueue, Msg, FALSE);
}
/* eat the message */
IntReleaseWindowObject(Wnd);
@@ -1114,6 +1117,13 @@ NtUserPostMessage(HWND Wnd,
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
}
if(Window->Status & WINDOWSTATUS_DESTROYING)
{
IntReleaseWindowObject(Window);
DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd);
/* FIXME - last error code? */
return FALSE;
}
UserModeMsg.hwnd = Wnd;
UserModeMsg.message = Msg;
@@ -1293,6 +1303,14 @@ IntSendMessageTimeoutSingle(HWND hWnd,
return FALSE;
}
if(Window->Status & WINDOWSTATUS_DESTROYING)
{
IntReleaseWindowObject(Window);
/* FIXME - last error? */
DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
return FALSE;
}
Status = MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam,
uTimeout, (uFlags & SMTO_BLOCK), uResult);
IntReleaseWindowObject(Window);
+81 -1
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: msgqueue.c,v 1.109 2004/12/10 22:40:29 weiden Exp $
/* $Id: msgqueue.c,v 1.110 2004/12/11 19:39:18 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -809,6 +809,84 @@ Notified:
return(TRUE);
}
VOID STDCALL
MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
{
PUSER_SENT_MESSAGE SentMessage;
PUSER_MESSAGE PostedMessage;
PUSER_MESSAGE_QUEUE MessageQueue;
PLIST_ENTRY CurrentEntry, ListHead;
PWINDOW_OBJECT Window = pWindow;
ASSERT(Window);
MessageQueue = Window->MessageQueue;
ASSERT(MessageQueue);
IntLockMessageQueue(MessageQueue);
/* remove the posted messages for this window */
CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
ListHead = &MessageQueue->PostedMessagesListHead;
while (CurrentEntry != ListHead)
{
PostedMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
ListEntry);
if (PostedMessage->Msg.hwnd == Window->Self)
{
RemoveEntryList(&PostedMessage->ListEntry);
MsqDestroyMessage(PostedMessage);
CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
}
else
{
CurrentEntry = CurrentEntry->Flink;
}
}
/* remove the sent messages for this window */
CurrentEntry = MessageQueue->SentMessagesListHead.Flink;
ListHead = &MessageQueue->SentMessagesListHead;
while (CurrentEntry != ListHead)
{
CurrentEntry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
if(SentMessage->Msg.hwnd == Window->Self)
{
IntLockMessageQueue(SentMessage->SenderQueue);
DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
/* remove the message from the dispatching list */
if(SentMessage->DispatchingListEntry.Flink != NULL)
{
RemoveEntryList(&SentMessage->DispatchingListEntry);
}
/* wake the sender's thread */
if (SentMessage->CompletionEvent != NULL)
{
KeSetEvent(SentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
}
IntUnLockMessageQueue(SentMessage->SenderQueue);
/* dereference our and the sender's message queue */
IntDereferenceMessageQueue(MessageQueue);
IntDereferenceMessageQueue(SentMessage->SenderQueue);
/* free the message */
ExFreePool(SentMessage);
CurrentEntry = MessageQueue->SentMessagesListHead.Flink;
}
else
{
CurrentEntry = CurrentEntry->Flink;
}
}
IntUnLockMessageQueue(MessageQueue);
}
VOID FASTCALL
MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue,
PUSER_SENT_MESSAGE_NOTIFY NotifyMessage)
@@ -1138,6 +1216,7 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
IntLockMessageQueue(CurrentSentMessage->SenderQueue);
DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
/* remove the message from the dispatching list */
@@ -1151,6 +1230,7 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
{
KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
}
IntUnLockMessageQueue(CurrentSentMessage->SenderQueue);
/* dereference our and the sender's message queue */
IntDereferenceMessageQueue(MessageQueue);
+19 -45
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: window.c,v 1.250 2004/11/20 19:08:37 weiden Exp $
/* $Id: window.c,v 1.251 2004/12/11 19:39:18 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -278,6 +278,7 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
return 0;
}
Window->Status |= WINDOWSTATUS_DESTROYING;
Window->Flags &= ~WS_VISIBLE;
/* remove the window already at this point from the thread window list so we
don't get into trouble when destroying the thread windows while we're still
in IntDestroyWindow() */
@@ -290,7 +291,18 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
{
/* Send destroy messages */
IntSendDestroyMsg(Window->Self);
if(BelongsToThreadData)
IntSendMessage(Window->Self, WM_NCDESTROY, 0, 0);
}
/* from now on no messages can be sent to this window anymore */
IntLockThreadWindows(Window->OwnerThread->Tcb.Win32Thread);
Window->Status |= WINDOWSTATUS_DESTROYED;
/* don't remove the WINDOWSTATUS_DESTROYING bit */
IntUnLockThreadWindows(Window->OwnerThread->Tcb.Win32Thread);
/* flush the message queue */
MsqRemoveWindowMessagesFromQueue(Window);
/* free child windows */
Children = IntWinListChildren(Window);
@@ -313,23 +325,6 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
ExFreePool(Children);
}
if (SendMessages)
{
/*
* Clear the update region to make sure no WM_PAINT messages will be
* generated for this window while processing the WM_NCDESTROY.
*/
IntRedrawWindow(Window, NULL, 0,
RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
/*
* Send the WM_NCDESTROY to the window being destroyed.
*/
if(BelongsToThreadData)
IntSendMessage(Window->Self, WM_NCDESTROY, 0, 0);
}
/* reset shell window handles */
if(ThreadData->Desktop)
{
@@ -385,11 +380,6 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
IntDestroyScrollBars(Window);
IntLockThreadWindows(Window->OwnerThread->Tcb.Win32Thread);
Window->Status |= WINDOWSTATUS_DESTROYED;
/* don't remove the WINDOWSTATUS_DESTROYING bit */
IntUnLockThreadWindows(Window->OwnerThread->Tcb.Win32Thread);
/* remove the window from the class object */
IntLockClassWindows(Window->Class);
RemoveEntryList(&Window->ClassListEntry);
@@ -1403,7 +1393,6 @@ IntCreateWindowEx(DWORD dwExStyle,
HWND ParentWindowHandle;
HWND OwnerWindowHandle;
PMENU_OBJECT SystemMenu;
NTSTATUS Status;
HANDLE Handle;
POINT Pos;
SIZE Size;
@@ -1417,7 +1406,6 @@ IntCreateWindowEx(DWORD dwExStyle,
LRESULT Result;
BOOL MenuChanged;
BOOL ClassFound;
PWSTR ClassNameString;
ParentWindowHandle = PsGetWin32Thread()->Desktop->DesktopWindow;
OwnerWindowHandle = NULL;
@@ -1454,24 +1442,7 @@ IntCreateWindowEx(DWORD dwExStyle,
/* FIXME: parent must belong to the current process */
/* Check the class. */
if (IS_ATOM(ClassName->Buffer))
{
ClassFound = ClassReferenceClassByNameOrAtom(&ClassObject, ClassName->Buffer, hInstance);
}
else
{
Status = IntUnicodeStringToNULLTerminated(&ClassNameString, ClassName);
if (! NT_SUCCESS(Status))
{
if (NULL != ParentWindow)
{
IntReleaseWindowObject(ParentWindow);
}
return NULL;
}
ClassFound = ClassReferenceClassByNameOrAtom(&ClassObject, ClassNameString, hInstance);
IntFreeNULLTerminatedFromUnicodeString(ClassNameString, ClassName);
}
ClassFound = ClassReferenceClassByNameOrAtom(&ClassObject, ClassName->Buffer, hInstance);
if (!ClassFound)
{
if (IS_ATOM(ClassName->Buffer))
@@ -1486,6 +1457,7 @@ IntCreateWindowEx(DWORD dwExStyle,
{
IntReleaseWindowObject(ParentWindow);
}
SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS);
return((HWND)0);
}
@@ -2045,7 +2017,7 @@ NtUserCreateWindowEx(DWORD dwExStyle,
}
if (! IS_ATOM(ClassName.Buffer))
{
Status = IntSafeCopyUnicodeString(&ClassName, UnsafeClassName);
Status = IntSafeCopyUnicodeStringTerminateNULL(&ClassName, UnsafeClassName);
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
@@ -2111,6 +2083,8 @@ NtUserDestroyWindow(HWND Wnd)
{
PWINDOW_OBJECT Window;
BOOLEAN isChild;
DbgPrint("DestroyWindow:0x%x\n", Wnd);
Window = IntGetWindowObject(Wnd);
if (Window == NULL)
@@ -2453,7 +2427,7 @@ NtUserFindWindowEx(HWND hwndParent,
DPRINT1("Window class not found (%lx)\n", (ULONG_PTR)ClassName.Buffer);
else
DPRINT1("Window class not found (%S)\n", ClassName.Buffer);
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
SetLastWin32Error(ERROR_FILE_NOT_FOUND);
goto Cleanup;
}
}
+3 -2
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: winpos.c,v 1.124 2004/11/21 12:14:34 navaraf Exp $
/* $Id: winpos.c,v 1.125 2004/12/11 19:39:18 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -1321,7 +1321,8 @@ WinPosShowWindow(HWND Wnd, INT Cmd)
/* FIXME: Check for window destruction. */
if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
if ((Window->Flags & WINDOWOBJECT_NEED_SIZE) &&
!(Window->Status & WINDOWSTATUS_DESTROYING))
{
WPARAM wParam = SIZE_RESTORED;