From e0d8684a66aea5bbf3ed66a184018608bae3531a Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sat, 2 Jun 2012 03:34:04 +0000 Subject: [PATCH] [Win32SS] - Minor fixups to SetParent. - Add utilities to check thread queue states and verify window object is still alive. svn path=/trunk/; revision=56688 --- reactos/win32ss/include/ntuser.h | 5 +- reactos/win32ss/user/ntuser/misc.c | 4 ++ reactos/win32ss/user/ntuser/object.c | 14 +++++ reactos/win32ss/user/ntuser/object.h | 1 + reactos/win32ss/user/ntuser/window.c | 93 +++++++++++++++++++++------- reactos/win32ss/user/ntuser/window.h | 1 + 6 files changed, 93 insertions(+), 25 deletions(-) diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index 0a21bb9bb29..91abf8fabb7 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -794,6 +794,7 @@ typedef LONG_PTR (NTAPI *PFN_FNID)(PWND, UINT, WPARAM, LPARAM, ULONG_PTR); #define SRVINFO_APIHOOK 0x0010 #define SRVINFO_METRICS 0x0020 +#define SRVINFO_KBDPREF 0x0080 #define NUM_SYSCOLORS 31 @@ -2182,7 +2183,8 @@ enum ThreadStateRoutines THREADSTATE_TASKMANWINDOW, THREADSTATE_GETMESSAGETIME, THREADSTATE_GETINPUTSTATE, - THREADSTATE_UPTIMELASTREAD + THREADSTATE_UPTIMELASTREAD, + THREADSTATE_FOREGROUNDTHREAD }; DWORD_PTR @@ -2522,6 +2524,7 @@ NtUserQueryUserCounters( #define QUERY_WINDOW_FOCUS 0x03 #define QUERY_WINDOW_ISHUNG 0x04 #define QUERY_WINDOW_REAL_ID 0x05 +#define QUERY_WINDOW_FOREGROUND 0x06 DWORD NTAPI NtUserQueryWindow( diff --git a/reactos/win32ss/user/ntuser/misc.c b/reactos/win32ss/user/ntuser/misc.c index 3c8321f1f82..0ed1e37c001 100644 --- a/reactos/win32ss/user/ntuser/misc.c +++ b/reactos/win32ss/user/ntuser/misc.c @@ -221,6 +221,10 @@ NtUserGetThreadState( case THREADSTATE_GETINPUTSTATE: ret = LOWORD(IntGetQueueStatus(QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_SENDMESSAGE|QS_INPUT)) & (QS_KEY | QS_MOUSEBUTTON); break; + + case THREADSTATE_FOREGROUNDTHREAD: + ret = (gpqForeground == GetW32ThreadInfo()->MessageQueue); + break; } TRACE("Leave NtUserGetThreadState, ret=%i\n", ret); diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index a464655e06e..f5131399c81 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -422,6 +422,20 @@ UserFreeHandle(PUSER_HANDLE_TABLE ht, HANDLE handle ) return UserDereferenceObject(entry->ptr); } +BOOL +FASTCALL +UserObjectInDestroy(HANDLE h) +{ + PUSER_HANDLE_ENTRY entry; + + if (!(entry = handle_to_entry( gHandleTable, h ))) + { + SetLastNtError( STATUS_INVALID_HANDLE ); + return FALSE; + } + return (entry->flags & HANDLEENTRY_INDESTROY); +} + BOOL FASTCALL UserDeleteObject(HANDLE h, USER_OBJECT_TYPE type ) diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index a9ea3dda01b..cc6d933d1df 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -37,6 +37,7 @@ PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, struct _DESKTOP* pDesktop BOOL FASTCALL UserDeleteObject(HANDLE h, USER_OBJECT_TYPE type ); PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type ); BOOL FASTCALL UserCreateHandleTable(VOID); +BOOL FASTCALL UserObjectInDestroy(HANDLE); static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry) diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 8a336e7e09e..3f110ce5b9d 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -59,6 +59,33 @@ PWND FASTCALL IntGetWindowObject(HWND hWnd) return Window; } +PWND FASTCALL VerifyWnd(PWND pWnd) +{ + HWND hWnd; + UINT State, State2; + + if (!pWnd) return NULL; + + _SEH2_TRY + { + hWnd = UserHMGetHandle(pWnd); + State = pWnd->state; + State2 = pWnd->state2; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + _SEH2_YIELD(return NULL); + } + _SEH2_END + + if ( UserObjectInDestroy(hWnd) || + State & WNDS_DESTROYED || + State2 & WNDS2_INDESTROY ) + return NULL; + + return pWnd; +} + /* Temp HACK */ PWND FASTCALL UserGetWindowObject(HWND hWnd) { @@ -144,7 +171,7 @@ IntGetParent(PWND Wnd) { if (Wnd->style & WS_POPUP) { - return Wnd->spwndOwner; + return Wnd->spwndOwner; } else if (Wnd->style & WS_CHILD) { @@ -1039,6 +1066,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) PWND WndOldParent, pWndExam; BOOL WasVisible; POINT pt; + int swFlags = SWP_NOSIZE|SWP_NOZORDER; ASSERT(Wnd); ASSERT(WndNewParent); @@ -1080,11 +1108,15 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) if (Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process()) return NULL; - pt.x = Wnd->rcWindow.left; - pt.y = Wnd->rcWindow.top; - WndOldParent = Wnd->spwndParent; + if ( WndOldParent && + WndOldParent->ExStyle & WS_EX_LAYOUTRTL) + pt.x = Wnd->rcWindow.right; + else + pt.x = Wnd->rcWindow.left; + pt.y = Wnd->rcWindow.top; + if (WndOldParent) UserReferenceObject(WndOldParent); /* Caller must deref */ if (WndNewParent != WndOldParent) @@ -1095,11 +1127,24 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) /* Set the new parent */ Wnd->spwndParent = WndNewParent; + if ( Wnd->style & WS_CHILD && + Wnd->spwndOwner && + Wnd->spwndOwner->ExStyle & WS_EX_TOPMOST ) + { + ERR("SetParent Top Most from Pop up!\n"); + Wnd->ExStyle |= WS_EX_TOPMOST; + } + /* Link the window with its new siblings */ - IntLinkHwnd(Wnd, HWND_TOP); + IntLinkHwnd( Wnd, + ((0 == (Wnd->ExStyle & WS_EX_TOPMOST) && + WndNewParent == UserGetDesktopWindow() ) ? HWND_TOP : HWND_TOPMOST ) ); } + if (WndOldParent == UserGetMessageWindow() || WndNewParent == UserGetMessageWindow()) + swFlags |= SWP_NOACTIVATE; + IntNotifyWinEvent(EVENT_OBJECT_PARENTCHANGE, Wnd ,OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); /* * SetParent additionally needs to make hwnd the top window @@ -1108,7 +1153,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent) */ co_WinPosSetWindowPos( Wnd, (0 == (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOP : HWND_TOPMOST), - pt.x, pt.y, 0, 0, SWP_NOSIZE ); + pt.x, pt.y, 0, 0, swFlags); if (WasVisible) co_WinPosShowWindow(Wnd, SW_SHOWNORMAL); @@ -1156,9 +1201,9 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent) UserRefObjectCo(Wnd, &Ref); UserRefObjectCo(WndParent, &ParentRef); - + //ERR("Enter co_IntSetParent\n"); WndOldParent = co_IntSetParent(Wnd, WndParent); - + //ERR("Leave co_IntSetParent\n"); UserDerefObjectCo(WndParent); UserDerefObjectCo(Wnd); @@ -1526,7 +1571,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, * Dialog boxes and message boxes do not inherit layout, so you must * set the layout explicitly. */ - if ( Class->fnid != FNID_DIALOG) + if ( Class->fnid != FNID_DIALOG ) { PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); if (ppi->dwLayout & LAYOUT_RTL) @@ -2077,16 +2122,11 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, if (style & (WS_MINIMIZE | WS_MAXIMIZE)) { RECTL NewPos; - UINT16 SwFlag; - - SwFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE; - - co_WinPosMinMaximize(Window, SwFlag, &NewPos); - - SwFlag = ((Window->style & WS_CHILD) || UserGetActiveWindow()) ? - SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED : - SWP_NOZORDER | SWP_FRAMECHANGED; + UINT SwFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE; + SwFlag = co_WinPosMinMaximize(Window, SwFlag, &NewPos); + SwFlag |= SWP_NOZORDER|SWP_FRAMECHANGED; /* Frame always gets changed */ + if (!(style & WS_VISIBLE) || (style & WS_CHILD) || UserGetActiveWindow()) SwFlag |= SWP_NOACTIVATE; co_WinPosSetWindowPos(Window, 0, NewPos.left, NewPos.top, NewPos.right, NewPos.bottom, SwFlag); } @@ -2339,6 +2379,7 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) ASSERT_REFS_CO(Window); // FIXME: Temp HACK? hWnd = Window->head.h; + ti = PsGetCurrentThreadWin32Thread(); TRACE("co_UserDestroyWindow \n"); @@ -2370,9 +2411,9 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) * be destroying. */ if (!co_WinPosShowWindow(Window, SW_HIDE)) - { - if (UserGetActiveWindow() == Window->head.h) - { + { // Rule #1. + if (ti->MessageQueue->spwndActive == Window && ti->MessageQueue == IntGetFocusMessageQueue()) + { ERR("DestroyWindow AOW\n"); co_WinPosActivateOtherWindow(Window); } } @@ -2381,6 +2422,8 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) Window->head.pti->MessageQueue->spwndActive = NULL; if (Window->head.pti->MessageQueue->spwndFocus == Window) Window->head.pti->MessageQueue->spwndFocus = NULL; + if (Window->head.pti->MessageQueue->spwndActivePrev == Window) + Window->head.pti->MessageQueue->spwndActivePrev = NULL; if (Window->head.pti->MessageQueue->CaptureWindow == Window->head.h) Window->head.pti->MessageQueue->CaptureWindow = NULL; @@ -2388,8 +2431,6 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) * Check if this window is the Shell's Desktop Window. If so set hShellWindow to NULL */ - ti = PsGetCurrentThreadWin32Thread(); - if ((ti != NULL) & (ti->pDeskInfo != NULL)) { if (ti->pDeskInfo->hShellWindow == hWnd) @@ -3092,7 +3133,7 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView) * -- Filip, 01/nov/2003 */ #if 0 - co_WinPosSetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + co_WinPosSetWindowPos(WndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); #endif if (WndListView->ExStyle & WS_EX_TOPMOST) @@ -3518,6 +3559,10 @@ NtUserQueryWindow(HWND hWnd, DWORD Index) Result = (DWORD)pWnd->head.pti->pEThread->Cid.UniqueProcess; break; + case QUERY_WINDOW_FOREGROUND: + Result = (pWnd->head.pti->MessageQueue == gpqForeground); + break; + default: Result = (DWORD)NULL; break; diff --git a/reactos/win32ss/user/ntuser/window.h b/reactos/win32ss/user/ntuser/window.h index 02a6f9cdb53..0dadd36374e 100644 --- a/reactos/win32ss/user/ntuser/window.h +++ b/reactos/win32ss/user/ntuser/window.h @@ -51,5 +51,6 @@ PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW*, PUNICODE_STRING, PLARGE_STRI BOOL FASTCALL IntEnableWindow(HWND,BOOL); DWORD FASTCALL GetNCHitEx(PWND,POINT); ULONG FASTCALL IntSetStyle(PWND,ULONG,ULONG); +PWND FASTCALL VerifyWnd(PWND); /* EOF */