mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-30 19:26:05 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user