Author: jimtabor Date: Mon Aug 13 07:16:01 2012 New Revision: 57068
URL: http://svn.reactos.org/svn/reactos?rev=57068&view=rev Log: [NtUser] - Fix bug 6751, 7228 and others, Validate link windows, not relink them per say. - Stop spurious window handle errors. This fixes all of the DeferWinPos handle errors.
Modified: trunk/reactos/win32ss/user/ntuser/object.c trunk/reactos/win32ss/user/ntuser/object.h trunk/reactos/win32ss/user/ntuser/window.c trunk/reactos/win32ss/user/ntuser/window.h trunk/reactos/win32ss/user/ntuser/winpos.c
Modified: trunk/reactos/win32ss/user/ntuser/object.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/object.... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/object.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/object.c [iso-8859-1] Mon Aug 13 07:16:01 2012 @@ -203,6 +203,20 @@ return entry_to_handle(ht, entry ); }
+/* return a pointer to a user object from its handle without setting an error */ +PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type ) +{ + PUSER_HANDLE_ENTRY entry; + + ASSERT(ht); + + if (!(entry = handle_to_entry(ht, handle )) || entry->type != type) + { + return NULL; + } + return entry->ptr; +} + /* return a pointer to a user object from its handle */ PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type ) {
Modified: trunk/reactos/win32ss/user/ntuser/object.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/object.... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/object.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/object.h [iso-8859-1] Mon Aug 13 07:16:01 2012 @@ -36,6 +36,7 @@ PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, struct _DESKTOP* pDesktop, HANDLE* h,USER_OBJECT_TYPE type , ULONG size); BOOL FASTCALL UserDeleteObject(HANDLE h, USER_OBJECT_TYPE type ); PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type ); +PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, USER_OBJECT_TYPE); BOOL FASTCALL UserCreateHandleTable(VOID); BOOL FASTCALL UserObjectInDestroy(HANDLE);
Modified: trunk/reactos/win32ss/user/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/window.... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/window.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/window.c [iso-8859-1] Mon Aug 13 07:16:01 2012 @@ -84,6 +84,12 @@ return NULL;
return pWnd; +} + +PWND FASTCALL ValidateHwndNoErr(HWND hWnd) +{ + if (hWnd) return (PWND)UserGetObjectNoErr(gHandleTable, hWnd, otWindow); + return NULL; }
/* Temp HACK */
Modified: trunk/reactos/win32ss/user/ntuser/window.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/window.... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/window.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/window.h [iso-8859-1] Mon Aug 13 07:16:01 2012 @@ -34,7 +34,7 @@ #define IntGetWndProcessId(WndObj) \ PsGetProcessId(WndObj->head.pti->ppi->peProcess)
- +PWND FASTCALL ValidateHwndNoErr(HWND); BOOL FASTCALL UserUpdateUiState(PWND Wnd, WPARAM wParam); BOOL FASTCALL IntIsWindow(HWND hWnd); HWND* FASTCALL IntWinListChildren(PWND Window);
Modified: trunk/reactos/win32ss/user/ntuser/winpos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/winpos.... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/winpos.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/winpos.c [iso-8859-1] Mon Aug 13 07:16:01 2012 @@ -28,12 +28,14 @@ #define PLACE_MAX 0x0002 #define PLACE_RECT 0x0004
+VOID FASTCALL IntLinkWindow(PWND Wnd,PWND WndInsertAfter); + /* FUNCTIONS *****************************************************************/
BOOL FASTCALL IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point) { - Window = Window ? Window : UserGetWindowObject(IntGetDesktopWindow()); + Window = Window ? Window : UserGetDesktopWindow(); if (Window == NULL) { Point->x = Point->y = 0; @@ -1091,6 +1093,10 @@ /* * Fix Z order taking into account owned popups - * basically we need to maintain them above the window that owns them + * + * FIXME: hide/show owned popups when owner visibility changes. + * + * ReactOS: See bug 6751 and 7228. */ static HWND FASTCALL @@ -1123,7 +1129,7 @@ break; if (HWND_TOP == hWndInsertAfter) { - ChildObject = UserGetWindowObject(List[i]); + ChildObject = ValidateHwndNoErr(List[i]); if (NULL != ChildObject) { if (0 == (ChildObject->ExStyle & WS_EX_TOPMOST)) @@ -1148,7 +1154,7 @@
if (!List) { - DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); + DesktopWindow = UserGetDesktopWindow(); List = IntWinListChildren(DesktopWindow); } if (List != NULL) @@ -1160,7 +1166,7 @@ if (List[i] == Window->head.h) break;
- if (!(Wnd = UserGetWindowObject(List[i]))) + if (!(Wnd = ValidateHwndNoErr(List[i]))) continue;
if (Wnd->style & WS_POPUP && Wnd->spwndOwner == Window) @@ -1169,7 +1175,7 @@ UserRefObjectCo(Wnd, &Ref);
co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE);
UserDerefObjectCo(Wnd);
@@ -1281,6 +1287,9 @@
if (WinPos->hwndInsertAfter == HWND_NOTOPMOST) { + if (!(Wnd->ExStyle & WS_EX_TOPMOST)) + WinPos->flags |= SWP_NOZORDER; + WinPos->hwndInsertAfter = HWND_TOP; } else if (HWND_TOP == WinPos->hwndInsertAfter @@ -1298,7 +1307,7 @@ { PWND InsAfterWnd;
- InsAfterWnd = UserGetWindowObject(WinPos->hwndInsertAfter); + InsAfterWnd = ValidateHwndNoErr(WinPos->hwndInsertAfter); if(!InsAfterWnd) { return TRUE; @@ -1361,6 +1370,7 @@ RECTL CopyRect; PWND Ancestor; BOOL bPointerInWindow; + BOOL bNoTopMost;
ASSERT_REFS_CO(Window);
@@ -1388,9 +1398,13 @@
co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
+ // HWND_NOTOPMOST is redirected in WinPosFixupFlags. + bNoTopMost = WndInsertAfter == HWND_NOTOPMOST; + /* Does the window still exist? */ if (!IntIsWindow(WinPos.hwnd)) { + TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos.hwnd); EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); return FALSE; } @@ -1403,8 +1417,7 @@ }
Ancestor = UserGetAncestor(Window, GA_PARENT); - if ( (WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != - SWP_NOZORDER && + if ( (WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER && Ancestor && Ancestor->head.h == IntGetDesktopWindow() ) { WinPos.hwndInsertAfter = WinPosDoOwnedPopups(Window, WinPos.hwndInsertAfter); @@ -1440,12 +1453,72 @@
WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
- TRACE("co_WinPosDoNCCALCSize returned %d\n", WvrFlags); - - /* Relink windows. (also take into account shell window in hwndShellWindow) */ + TRACE("co_WinPosDoNCCALCSize returned %d\n", WvrFlags); + + /* Validate link windows. (also take into account shell window in hwndShellWindow) */ if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow()) { - IntLinkHwnd(Window, WndInsertAfter); + //// Fix bug 6751 & 7228 see WinPosDoOwnedPopups wine Fixme. + PWND ParentWindow; + PWND Sibling; + PWND InsertAfterWindow; + + if ((ParentWindow = Window->spwndParent)) // Must have a Parent window! + { + if (WinPos.hwndInsertAfter == HWND_TOPMOST) + { + InsertAfterWindow = NULL; + } + else if ( WinPos.hwndInsertAfter == HWND_TOP ) + { + InsertAfterWindow = NULL; + + Sibling = ParentWindow->spwndChild; + + while ( Sibling && Sibling->ExStyle & WS_EX_TOPMOST ) + { + InsertAfterWindow = Sibling; + Sibling = Sibling->spwndNext; + } + } + else if (WinPos.hwndInsertAfter == HWND_BOTTOM) + { + if (ParentWindow->spwndChild) + { + InsertAfterWindow = ParentWindow->spwndChild; + + if(InsertAfterWindow) + { + while (InsertAfterWindow->spwndNext) + InsertAfterWindow = InsertAfterWindow->spwndNext; + } + } + else + InsertAfterWindow = NULL; + } + else + InsertAfterWindow = IntGetWindowObject(WinPos.hwndInsertAfter); + /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already + the last window */ + if (InsertAfterWindow != Window) + { + IntUnlinkWindow(Window); + IntLinkWindow(Window, InsertAfterWindow); + } + + if ( ( WinPos.hwndInsertAfter == HWND_TOPMOST || + ( Window->ExStyle & WS_EX_TOPMOST && Window->spwndPrev && Window->spwndPrev->ExStyle & WS_EX_TOPMOST ) || + ( Window->spwndNext && Window->spwndNext->ExStyle & WS_EX_TOPMOST ) ) && + !bNoTopMost ) + { + Window->ExStyle |= WS_EX_TOPMOST; + } + else + { + Window->ExStyle &= ~ WS_EX_TOPMOST; + } + } + //// }
OldWindowRect = Window->rcWindow; @@ -1476,6 +1549,7 @@ Window->rcWindow = NewWindowRect; Window->rcClient = NewClientRect;
+ /* erase parent when hiding or resizing child */ if (WinPos.flags & SWP_HIDEWINDOW) { /* Clear the update region */ @@ -1487,14 +1561,16 @@ if (Window->spwndParent == UserGetDesktopWindow()) co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM)Window->head.h);
- Window->style &= ~WS_VISIBLE; + Window->style &= ~WS_VISIBLE; //IntSetStyle( Window, 0, WS_VISIBLE ); + IntNotifyWinEvent(EVENT_OBJECT_HIDE, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); } else if (WinPos.flags & SWP_SHOWWINDOW) { if (Window->spwndParent == UserGetDesktopWindow()) co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Window->head.h);
- Window->style |= WS_VISIBLE; + Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 ); + IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); }
if (Window->hrgnUpdate != NULL && Window->hrgnUpdate != HRGN_WINDOW) @@ -1504,7 +1580,7 @@ NewWindowRect.top - OldWindowRect.top); }
- DceResetActiveDCEs(Window); + DceResetActiveDCEs(Window); // For WS_VISIBLE changes.
if (!(WinPos.flags & SWP_NOREDRAW)) { @@ -1724,6 +1800,10 @@ } }
+ /* And last, send the WM_WINDOWPOSCHANGED message */ + + TRACE("\tstatus flags = %04x\n", WinPos.flags & SWP_AGG_STATUSFLAGS); + if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) { /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set @@ -1739,7 +1819,7 @@ if ( WinPos.flags & SWP_FRAMECHANGED || WinPos.flags & SWP_STATECHANGED || !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) ) { - PWND pWnd = UserGetWindowObject(WinPos.hwnd); + PWND pWnd = ValidateHwndNoErr(WinPos.hwnd); if (pWnd) IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); } @@ -2297,7 +2377,7 @@ winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y, winpos->pos.cx, winpos->pos.cy, winpos->pos.flags);
- pwnd = (PWND)UserGetObject(gHandleTable, winpos->pos.hwnd, otWindow); + pwnd = ValidateHwndNoErr(winpos->pos.hwnd); if (!pwnd) continue;
@@ -2328,6 +2408,10 @@ winpos->pos.cy, winpos->pos.flags);
+ // Hack to pass tests.... Must have some work to do so clear the error. + if (res && (winpos->pos.flags & (SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER)) == SWP_NOZORDER ) + EngSetLastError(ERROR_SUCCESS); + UserDerefObjectCo(pwnd); } ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP); @@ -2335,7 +2419,6 @@ UserDeleteObject(hdwp, otSMWP); return res; } -
/* * @implemented