[Win32k|User32]
authorJames Tabor <james.tabor@reactos.org>
Sat, 10 Dec 2011 07:41:56 +0000 (07:41 +0000)
committerJames Tabor <james.tabor@reactos.org>
Sat, 10 Dec 2011 07:41:56 +0000 (07:41 +0000)
- Fix Get/SetWindowPlacement and everything related. Which exposed the scroll bar over write issue, it's not refreshing the client window when it is maximized. Next thing to fix.
- Fix ShowWindowAsync, now restore and minimize all works. This is based on wine but in reality it's based on Windows queuing event messages used in server side internal calls. Also this patch includes the server side hooking points.
- Removed one ugly API.
- Fixes bug 6239, 6739 and client window restore from maximize and the incremental crawling down issue when parent window is minimized then restored.

svn path=/trunk/; revision=54637

12 files changed:
reactos/dll/win32/user32/windows/input.c
reactos/dll/win32/user32/windows/window.c
reactos/dll/win32/user32/windows/winpos.c
reactos/include/reactos/win32k/ntuser.h
reactos/subsystems/win32/win32k/include/msgqueue.h
reactos/subsystems/win32/win32k/include/winpos.h
reactos/subsystems/win32/win32k/ntuser/message.c
reactos/subsystems/win32/win32k/ntuser/ntstubs.c
reactos/subsystems/win32/win32k/ntuser/window.c
reactos/subsystems/win32/win32k/ntuser/winpos.c
reactos/subsystems/win32/win32k/w32ksvc.db
reactos/subsystems/win32/win32k/w32ksvc.h

index b36faf3..b9c1d88 100644 (file)
@@ -557,8 +557,6 @@ keybd_event(
     BYTE bScan,
     DWORD dwFlags,
     ULONG_PTR dwExtraInfo)
-
-
 {
     INPUT Input;
 
index fc338da..03674e5 100644 (file)
@@ -959,6 +959,13 @@ GetClientRect(HWND hWnd, LPRECT lpRect)
     PWND Wnd = ValidateHwnd(hWnd);
 
     if (!Wnd) return FALSE;
+    if (Wnd->style & WS_MINIMIZED)
+    {
+       lpRect->left = lpRect->top = 0;
+       lpRect->right = GetSystemMetrics(SM_CXMINIMIZED);
+       lpRect->bottom = GetSystemMetrics(SM_CYMINIMIZED);
+       return TRUE;
+    }
     if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP ) 
     {
 /*        lpRect->left = lpRect->top = 0;
index 6ba6e98..a6c04cf 100644 (file)
@@ -68,26 +68,110 @@ WinPosActivateOtherWindow(HWND hwnd)
     if (!SetActiveWindow( hwndTo )) SetActiveWindow(0);
 }
 
-
+#define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
 
 UINT WINAPI
-WinPosGetMinMaxInfo(HWND hWnd, POINT* MaxSize, POINT* MaxPos,
-                 POINT* MinTrack, POINT* MaxTrack)
+WinPosGetMinMaxInfo(HWND hwnd, POINT* maxSize, POINT* maxPos,
+                 POINT* minTrack, POINT* maxTrack)
 {
-  MINMAXINFO MinMax;
-
-  if(NtUserGetMinMaxInfo(hWnd, &MinMax, TRUE))
-  {
-    MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
-                                 MinMax.ptMinTrackSize.x);
-    MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
-                                 MinMax.ptMinTrackSize.y);
-
-    if (MaxSize) *MaxSize = MinMax.ptMaxSize;
-    if (MaxPos) *MaxPos = MinMax.ptMaxPosition;
-    if (MinTrack) *MinTrack = MinMax.ptMinTrackSize;
-    if (MaxTrack) *MaxTrack = MinMax.ptMaxTrackSize;
-  }
+    MINMAXINFO MinMax;
+    HMONITOR monitor;
+    INT xinc, yinc;
+    LONG style = GetWindowLongW( hwnd, GWL_STYLE );
+    LONG adjustedStyle;
+    LONG exstyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
+    RECT rc;
+    WND *win;
+
+    /* Compute default values */
+
+    GetWindowRect(hwnd, &rc);
+    MinMax.ptReserved.x = rc.left;
+    MinMax.ptReserved.y = rc.top;
+
+    if ((style & WS_CAPTION) == WS_CAPTION)
+        adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
+    else
+        adjustedStyle = style;
+
+    GetClientRect(GetAncestor(hwnd,GA_PARENT), &rc);
+    AdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle);
+
+    xinc = -rc.left;
+    yinc = -rc.top;
+
+    MinMax.ptMaxSize.x = rc.right - rc.left;
+    MinMax.ptMaxSize.y = rc.bottom - rc.top;
+    if (style & (WS_DLGFRAME | WS_BORDER))
+    {
+        MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
+        MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
+    }
+    else
+    {
+        MinMax.ptMinTrackSize.x = 2 * xinc;
+        MinMax.ptMinTrackSize.y = 2 * yinc;
+    }
+    MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
+    MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
+    MinMax.ptMaxPosition.x = -xinc;
+    MinMax.ptMaxPosition.y = -yinc;
+
+    if ((win = ValidateHwnd( hwnd )) )//&& win != WND_DESKTOP && win != WND_OTHER_PROCESS)
+    {
+        if (!EMPTYPOINT(win->InternalPos.MaxPos)) MinMax.ptMaxPosition = win->InternalPos.MaxPos;
+    }
+
+    SendMessageW( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
+
+    /* if the app didn't change the values, adapt them for the current monitor */
+
+    if ((monitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY )))
+    {
+        RECT rc_work;
+        MONITORINFO mon_info;
+
+        mon_info.cbSize = sizeof(mon_info);
+        GetMonitorInfoW( monitor, &mon_info );
+
+        rc_work = mon_info.rcMonitor;
+
+        if (style & WS_MAXIMIZEBOX)
+        {
+            if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP)))
+                rc_work = mon_info.rcWork;
+        }
+
+        if (MinMax.ptMaxSize.x == GetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
+            MinMax.ptMaxSize.y == GetSystemMetrics(SM_CYSCREEN) + 2 * yinc)
+        {
+            MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
+            MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
+        }
+        if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
+        {
+            MinMax.ptMaxPosition.x = rc_work.left - xinc;
+            MinMax.ptMaxPosition.y = rc_work.top - yinc;
+        }
+    }
+
+      /* Some sanity checks */
+
+    TRACE("%d %d / %d %d / %d %d / %d %d\n",
+                      MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
+                      MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
+                      MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
+                      MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
+    MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
+                                   MinMax.ptMinTrackSize.x );
+    MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
+                                   MinMax.ptMinTrackSize.y );
+
+    if (maxSize) *maxSize = MinMax.ptMaxSize;
+    if (maxPos) *maxPos = MinMax.ptMaxPosition;
+    if (minTrack) *minTrack = MinMax.ptMinTrackSize;
+    if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
+
   return 0; //FIXME: what does it return?
 }
 
index ea790bd..2598f83 100644 (file)
@@ -132,6 +132,7 @@ typedef struct _DESKTOPINFO
     WCHAR szDesktopName[1];
 } DESKTOPINFO, *PDESKTOPINFO;
 
+#define CTI_THREADSYSLOCK 0x0001
 #define CTI_INSENDMESSAGE 0x0002
 
 typedef struct _CLIENTTHREADINFO
@@ -567,6 +568,9 @@ typedef struct _SBINFOEX
 #define WS_EX2_CONSOLEWINDOW            0X00000400
 #define WS_EX2_CHILDNOACTIVATE          0X00000800
 
+#define WPF_MININIT    0x0008
+#define WPF_MAXINIT    0x0010
+
 typedef struct _WND
 {
     THRDESKHEAD head;
@@ -622,10 +626,10 @@ typedef struct _WND
         RECT NormalRect;
         POINT IconPos;
         POINT MaxPos;
+        UINT flags; // WPF_ flags.
     } InternalPos;
 
     UINT Unicode : 1; // !(WNDS_ANSICREATOR|WNDS_ANSIWINDOWPROC) ?
-    /* Indicates whether the window is derived from a system class */
     UINT InternalPosInitialized : 1;
     UINT HideFocus : 1; // WS_EX_UISTATEFOCUSRECTHIDDEN ?
     UINT HideAccel : 1; // WS_EX_UISTATEKBACCELHIDDEN ?
@@ -3213,8 +3217,8 @@ typedef struct tagKMDDEEXECUTEDATA
 
 typedef struct tagKMDDELPARAM
 {
-          UINT_PTR uiLo;
-          UINT_PTR uiHi;
+  UINT_PTR uiLo;
+  UINT_PTR uiHi;
 } KMDDELPARAM, *PKMDDELPARAM;
 
 
@@ -3258,13 +3262,6 @@ NtUserGetMenuDefaultItem(
   UINT fByPos,
   UINT gmdiFlags);
 
-BOOL
-NTAPI
-NtUserGetMinMaxInfo(
-  HWND hwnd,
-  MINMAXINFO *MinMaxInfo,
-  BOOL SendMessage);
-
 BOOL
 NTAPI
 NtUserGetMonitorInfo(
index 073e402..d41b198 100644 (file)
@@ -142,6 +142,13 @@ typedef struct _USER_MESSAGE_QUEUE
 #define QF_CAPTURELOCKED          0x00100000
 #define QF_ACTIVEWNDTRACKING      0x00200000
 
+/* internal messages codes */
+enum internal_event_message
+{
+    WM_ASYNC_SHOWWINDOW = 0x80000000,
+    WM_ASYNC_SETWINDOWPOS
+};
+
 BOOL FASTCALL MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue);
 VOID CALLBACK HungAppSysTimerProc(HWND,UINT,UINT_PTR,DWORD);
 NTSTATUS FASTCALL co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
index e09ed1c..492529d 100644 (file)
@@ -54,4 +54,3 @@ BOOLEAN FASTCALL co_WinPosShowWindow(PWND Window, INT Cmd);
 void FASTCALL co_WinPosSendSizeMove(PWND Window);
 PWND FASTCALL co_WinPosWindowFromPoint(PWND ScopeWin, POINT *WinPoint, USHORT* HitTest);
 VOID FASTCALL co_WinPosActivateOtherWindow(PWND Window);
-VOID FASTCALL WinPosInitInternalPos(PWND WindowObject, POINT *pt, RECTL *RestoreRect);
index af3187d..c84c5e5 100644 (file)
@@ -99,6 +99,7 @@ static inline int is_pointer_message( UINT message )
     if (message >= 8*sizeof(message_pointer_flags)) return FALSE;
         return (message_pointer_flags[message / 32] & SET(message)) != 0;
 }
+#undef SET
 
 #define MMS_SIZE_WPARAM      -1
 #define MMS_SIZE_WPARAMWCHAR -2
@@ -590,6 +591,39 @@ IntCallWndProcRet ( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPar
     co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR );
 }
 
+static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+    LRESULT lRes;
+
+    if (!pWnd ||
+         pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
+         pWnd == IntGetMessageWindow() )  // pWnd->fnid == FNID_MESSAGEWND
+       return 0;
+
+    ERR("Internal Event Msg %p\n",msg);
+
+    switch(msg)
+    {
+       case WM_ASYNC_SHOWWINDOW:
+          return co_WinPosShowWindow( pWnd, wparam );
+       case WM_ASYNC_SETWINDOWPOS:
+       {
+          PWINDOWPOS winpos = (PWINDOWPOS)lparam;
+          if (!winpos) return 0;
+          lRes = co_WinPosSetWindowPos( pWnd,
+                                        winpos->hwndInsertAfter,
+                                        winpos->x,
+                                        winpos->y,
+                                        winpos->cx,
+                                        winpos->cy,
+                                        winpos->flags);
+          ExFreePoolWithTag(winpos, USERTAG_SWP);
+          return lRes;
+       }
+    }
+    return 0;
+}        
+
 LRESULT FASTCALL
 IntDispatchMessage(PMSG pMsg)
 {
@@ -648,6 +682,13 @@ IntDispatchMessage(PMSG pMsg)
     // Need a window!
     if ( !Window ) return 0;
 
+    if (pMsg->message == WM_PAINT) Window->state |= WNDS_PAINTNOTPROCESSED;
+
+    if ( Window->state & WNDS_SERVERSIDEWINDOWPROC )
+    {
+       TRACE("Dispatch: Server Side Window Procedure\n");
+    }
+
     /* Since we are doing a callback on the same thread right away, there is
        no need to copy the lparam to kernel mode and then back to usermode.
        We just pretend it isn't a pointer */
@@ -662,6 +703,7 @@ IntDispatchMessage(PMSG pMsg)
 
     if (pMsg->message == WM_PAINT)
     {
+        Window->state2 &= ~WNDS2_WMPAINTSENT;
         /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
         HRGN hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
         co_UserGetUpdateRgn( Window, hrgn, TRUE );
@@ -1096,7 +1138,7 @@ UserPostMessage( HWND Wnd,
         PWND DesktopWindow;
         ULONG i;
 
-        DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+        DesktopWindow = UserGetDesktopWindow();
         List = IntWinListChildren(DesktopWindow);
 
         if (List != NULL)
@@ -1104,6 +1146,13 @@ UserPostMessage( HWND Wnd,
             UserPostMessage(DesktopWindow->head.h, Msg, wParam, lParam);
             for (i = 0; List[i]; i++)
             {
+                PWND pwnd = UserGetWindowObject(List[i]);
+                if (!pwnd) continue;
+
+                if ( pwnd->fnid == FNID_MENU || // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
+                     pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] )
+                   continue;
+
                 UserPostMessage(List[i], Msg, wParam, lParam);
             }
             ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
@@ -1145,7 +1194,6 @@ UserPostMessage( HWND Wnd,
     return TRUE;
 }
 
-
 LRESULT FASTCALL
 co_IntSendMessage( HWND hWnd,
                    UINT Msg,
@@ -1175,7 +1223,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
     INT lParamBufferSize;
     LPARAM lParamPacked;
     PTHREADINFO Win32Thread;
-    ULONG_PTR Result = 0;
+    ULONG_PTR Hi, Lo, Result = 0;
     DECLARE_RETURN(LRESULT);
     USER_REFERENCE_ENTRY Ref;
 
@@ -1188,8 +1236,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
 
     Win32Thread = PsGetCurrentThreadWin32Thread();
 
-
-    if ( NULL != Win32Thread &&
+    if ( Win32Thread &&
          Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
     {
         if (Win32Thread->TIF_flags & TIF_INCLEANUP)
@@ -1198,23 +1245,44 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
             RETURN( FALSE);
         }
 
+        if (Msg & 0x80000000)
+        {
+           ERR("SMTS: Internal Message!\n");
+           Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam );
+           if (uResult) *uResult = Result;
+           RETURN( TRUE);
+        }
+
+        // Only happens when calling the client!
         IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
 
+        if ( Window->state & WNDS_SERVERSIDEWINDOWPROC )
+        {
+           TRACE("SMT: Server Side Window Procedure\n");
+           IoGetStackLimits(&Lo, &Hi);
+           // Handle it here. Safeguard against excessive recursions.
+           if (((ULONG_PTR)&uResult - Lo) < 4096 )
+           {
+              ERR("Server Callback Exceeded Stack!\n");
+              RETURN( FALSE);
+           }
+           /* Return after server side call, IntCallWndProcRet will not be called. */
+        }
         /* See if this message type is present in the table */
         MsgMemoryEntry = FindMsgMemory(Msg);
         if (NULL == MsgMemoryEntry)
         {
-            lParamBufferSize = -1;
+           lParamBufferSize = -1;
         }
         else
         {
-            lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+           lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
         }
 
         if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, FALSE)))
         {
-            ERR("Failed to pack message parameters\n");
-            RETURN( FALSE);
+           ERR("Failed to pack message parameters\n");
+           RETURN( FALSE);
         }
 
         Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
@@ -1229,14 +1297,15 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
             *uResult = Result;
         }
 
-        IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
-
         if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
         {
             ERR("Failed to unpack message parameters\n");
             RETURN( TRUE);
         }
 
+        // Only happens when calling the client!
+        IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+
         RETURN( TRUE);
     }
 
@@ -1283,7 +1352,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
         EngSetLastError(ERROR_TIMEOUT);
         RETURN( FALSE);
     }
-    else if (! NT_SUCCESS(Status))
+    else if (!NT_SUCCESS(Status))
     {
         SetLastNtError(Status);
         RETURN( FALSE);
@@ -1309,20 +1378,23 @@ co_IntSendMessageTimeout( HWND hWnd,
     HWND *Children;
     HWND *Child;
 
-    if (HWND_BROADCAST != hWnd)
+    if (hWnd != HWND_BROADCAST && hWnd != HWND_TOPMOST)
     {
         return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
     }
 
-    DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+    DesktopWindow = UserGetDesktopWindow();
     if (NULL == DesktopWindow)
     {
-        EngSetLastError(ERROR_INTERNAL_ERROR);
-        return 0;
+       EngSetLastError(ERROR_INTERNAL_ERROR);
+       return 0;
     }
 
-    /* Send message to the desktop window too! */
-    co_IntSendMessageTimeoutSingle(DesktopWindow->head.h, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+    if (hWnd != HWND_TOPMOST)
+    {
+       /* Send message to the desktop window too! */
+       co_IntSendMessageTimeoutSingle(DesktopWindow->head.h, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+    }
 
     Children = IntWinListChildren(DesktopWindow);
     if (NULL == Children)
@@ -1332,7 +1404,26 @@ co_IntSendMessageTimeout( HWND hWnd,
 
     for (Child = Children; NULL != *Child; Child++)
     {
-        co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+        if (hWnd == HWND_TOPMOST)
+        {
+           DesktopWindow = UserGetWindowObject(*Child);
+           if (DesktopWindow && DesktopWindow->ExStyle & WS_EX_TOPMOST)
+           {
+              ERR("HWND_TOPMOST Found\n");
+              co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+           }
+        }
+        else
+        {
+           PWND pwnd = UserGetWindowObject(*Child);
+           if (!pwnd) continue;
+
+           if ( pwnd->fnid == FNID_MENU ||
+                pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] )
+              continue;
+
+           co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+        }
     }
 
     ExFreePool(Children);
@@ -1347,13 +1438,16 @@ co_IntSendMessageNoWait(HWND hWnd,
                         LPARAM lParam)
 {
     ULONG_PTR Result = 0;
-    co_IntSendMessageWithCallBack(hWnd,
-                                  Msg,
-                                  wParam,
-                                  lParam,
-                                  NULL,
-                                  0,
-                                  &Result);
+    if (!co_IntSendMessageWithCallBack( hWnd,
+                                        Msg,
+                                        wParam,
+                                        lParam,
+                                        NULL,
+                                        0,
+                                       &Result))
+    {
+       Result = ((ULONG_PTR)-1);
+    } 
     return Result;
 }
 /* MSDN:
@@ -1430,8 +1524,21 @@ co_IntSendMessageWithCallBack( HWND hWnd,
             RETURN(FALSE);
         }
 
+        if (Msg & 0x80000000)
+        {
+           ERR("SMWCB: Internal Message!\n");
+           Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam );
+           if (uResult) *uResult = Result;                              
+           RETURN( TRUE);
+        }
+
         IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
 
+        if ( Window->state & WNDS_SERVERSIDEWINDOWPROC )
+        {
+           TRACE("SMWCB: Server Side Window Procedure\n");
+        }
+
         Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
                                                   !Window->Unicode,
                                                   hWnd,
@@ -1505,9 +1612,12 @@ CLEANUP:
     END_CLEANUP;
 }
 
-/* This function posts a message if the destination's message queue belongs to
-another thread, otherwise it sends the message. It does not support broadcast
-messages! */
+
+/*
+  This HACK function posts a message if the destination's message queue belongs to
+  another thread, otherwise it sends the message. It does not support broadcast
+  messages! 
+*/
 LRESULT FASTCALL
 co_IntPostOrSendMessage( HWND hWnd,
                          UINT Msg,
@@ -1561,7 +1671,7 @@ co_IntDoSendMessage( HWND hWnd,
     MSG KernelModeMsg;
     PMSGMEMORY MsgMemoryEntry;
 
-    if (HWND_BROADCAST != hWnd)
+    if (hWnd != HWND_BROADCAST && hWnd != HWND_TOPMOST)
     {
         Window = UserGetWindowObject(hWnd);
         if ( !Window )
@@ -1641,7 +1751,7 @@ UserSendNotifyMessage( HWND hWnd,
         PWND DesktopWindow;
         ULONG i;
 
-        DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+        DesktopWindow = UserGetDesktopWindow();
         List = IntWinListChildren(DesktopWindow);
 
         if (List != NULL)
@@ -1649,21 +1759,22 @@ UserSendNotifyMessage( HWND hWnd,
             UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam);
             for (i = 0; List[i]; i++)
             {
-                Ret = UserSendNotifyMessage(List[i], Msg, wParam, lParam);
+               PWND pwnd = UserGetWindowObject(List[i]);
+               if (!pwnd) continue;
+
+               if ( pwnd->fnid == FNID_MENU ||
+                    pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_SWITCH] )
+                  continue;
+
+               Ret = UserSendNotifyMessage(List[i], Msg, wParam, lParam);
             }
             ExFreePool(List);
         }
     }
     else
     {
-        ULONG_PTR lResult = 0;
-        Ret = co_IntSendMessageWithCallBack( hWnd,
-                                             Msg,
-                                             wParam,
-                                             lParam,
-                                             NULL,
-                                             0,
-                                            &lResult);
+        Ret = co_IntSendMessageNoWait( hWnd, Msg, wParam, lParam);
+        if (-1 == (int) Ret || !Ret) Ret = FALSE;
     }
     return Ret;
 }
@@ -2255,7 +2366,7 @@ NtUserMessageCall( HWND hWnd,
                ULONG i;
                UINT fuFlags;
 
-               pwndDesk = UserGetWindowObject(IntGetDesktopWindow());
+               pwndDesk = UserGetDesktopWindow();
                List = IntWinListChildren(pwndDesk);
 
                if (parm.flags & BSF_QUERY)
index 2160be9..cd91ff6 100644 (file)
@@ -1040,21 +1040,6 @@ NtUserSetImeOwnerWindow(DWORD Unknown0,
    return 0;
 }
 
-/*
- * @unimplemented
- */
-DWORD APIENTRY
-NtUserSetInternalWindowPos(
-   HWND    hwnd,
-   UINT    showCmd,
-   LPRECT  rect,
-   LPPOINT pt)
-{
-   STUB
-
-   return 0;
-}
-
 /*
  * @unimplemented
  */
index 959f005..c6c4949 100644 (file)
@@ -1262,51 +1262,6 @@ IntUnlinkWindow(PWND Wnd)
    Wnd->spwndPrev = Wnd->spwndNext = NULL;
 }
 
-BOOL
-FASTCALL
-IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
-{
-   POINT Size;
-
-   if (!Wnd) return FALSE;
-
-   if(lpwndpl->length != sizeof(WINDOWPLACEMENT))
-   {
-      return FALSE;
-   }
-
-   lpwndpl->flags = 0;
-   if (0 == (Wnd->style & WS_VISIBLE))
-   {
-      lpwndpl->showCmd = SW_HIDE;
-   }
-   else if (0 != (Wnd->state2 & WNDS2_MAXIMIZEBUTTONDOWN) ||
-            0 != (Wnd->style & WS_MAXIMIZE))
-   {
-      lpwndpl->showCmd = SW_MAXIMIZE;
-   }
-   else if (0 != (Wnd->style & WS_MINIMIZE))
-   {
-      lpwndpl->showCmd = SW_MINIMIZE;
-   }
-   else if (0 != (Wnd->style & WS_VISIBLE))
-   {
-      lpwndpl->showCmd = SW_SHOWNORMAL;
-   }
-
-   Size.x = Wnd->rcWindow.left;
-   Size.y = Wnd->rcWindow.top;
-   WinPosInitInternalPos(Wnd, &Size,
-                         &Wnd->rcWindow);
-
-   lpwndpl->rcNormalPosition = Wnd->InternalPos.NormalRect;
-   lpwndpl->ptMinPosition = Wnd->InternalPos.IconPos;
-   lpwndpl->ptMaxPosition = Wnd->InternalPos.MaxPos;
-
-   return TRUE;
-}
-
-
 /* FUNCTIONS *****************************************************************/
 
 /*
@@ -3019,80 +2974,6 @@ CLEANUP:
 }
 
 
-/*
- * @implemented
- */
-DWORD APIENTRY
-NtUserGetInternalWindowPos( HWND hWnd,
-                            LPRECT rectWnd,
-                            LPPOINT ptIcon)
-{
-   PWND Window;
-   DWORD Ret = 0;
-   BOOL Hit = FALSE;
-   WINDOWPLACEMENT wndpl;
-
-   UserEnterShared();
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-      Hit = FALSE;
-      goto Exit;
-   }
-
-   _SEH2_TRY
-   {
-       if(rectWnd)
-       {
-          ProbeForWrite(rectWnd,
-                        sizeof(RECT),
-                        1);
-       }
-       if(ptIcon)
-       {
-          ProbeForWrite(ptIcon,
-                        sizeof(POINT),
-                        1);
-       }
-
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-       SetLastNtError(_SEH2_GetExceptionCode());
-       Hit = TRUE;
-   }
-   _SEH2_END;
-
-   wndpl.length = sizeof(WINDOWPLACEMENT);
-
-   if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
-   {
-      _SEH2_TRY
-      {
-          if (rectWnd)
-          {
-             RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
-          }
-          if (ptIcon)
-          {
-             RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
-          }
-
-      }
-      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-      {
-          SetLastNtError(_SEH2_GetExceptionCode());
-          Hit = TRUE;
-      }
-      _SEH2_END;
-
-      if (!Hit) Ret = wndpl.showCmd;
-   }
-Exit:
-   UserLeave();
-   return Ret;
-}
-
 DWORD
 APIENTRY
 NtUserGetListBoxInfo(
@@ -3595,82 +3476,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-/*
- * @implemented
- */
-BOOL APIENTRY
-NtUserGetWindowPlacement(HWND hWnd,
-                         WINDOWPLACEMENT *lpwndpl)
-{
-   PWND Wnd;
-   POINT Size;
-   WINDOWPLACEMENT Safepl;
-   NTSTATUS Status;
-   DECLARE_RETURN(BOOL);
-
-   TRACE("Enter NtUserGetWindowPlacement\n");
-   UserEnterShared();
-
-   if (!(Wnd = UserGetWindowObject(hWnd)))
-   {
-      RETURN( FALSE);
-   }
-
-   Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
-   if(!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN( FALSE);
-   }
-   if(Safepl.length != sizeof(WINDOWPLACEMENT))
-   {
-      RETURN( FALSE);
-   }
-
-   Safepl.flags = 0;
-   if (0 == (Wnd->style & WS_VISIBLE))
-   {
-      Safepl.showCmd = SW_HIDE;
-   }
-   else if ((0 != (Wnd->state2 & WNDS2_MAXIMIZEBUTTONDOWN) ||
-            0 != (Wnd->style & WS_MAXIMIZE)) &&
-            0 == (Wnd->style & WS_MINIMIZE))
-   {
-      Safepl.showCmd = SW_SHOWMAXIMIZED;
-   }
-   else if (0 != (Wnd->style & WS_MINIMIZE))
-   {
-      Safepl.showCmd = SW_SHOWMINIMIZED;
-   }
-   else if (0 != (Wnd->style & WS_VISIBLE))
-   {
-      Safepl.showCmd = SW_SHOWNORMAL;
-   }
-
-   Size.x = Wnd->rcWindow.left;
-   Size.y = Wnd->rcWindow.top;
-   WinPosInitInternalPos(Wnd, &Size,
-                         &Wnd->rcWindow);
-
-   Safepl.rcNormalPosition = Wnd->InternalPos.NormalRect;
-   Safepl.ptMinPosition = Wnd->InternalPos.IconPos;
-   Safepl.ptMaxPosition = Wnd->InternalPos.MaxPos;
-
-   Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
-   if(!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN( FALSE);
-   }
-
-   RETURN( TRUE);
-
-CLEANUP:
-   TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
 /*
  QueryWindow based on KJK::Hyperion and James Tabor.
 
@@ -3827,7 +3632,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-
 /*
  * @implemented
  */
@@ -3872,57 +3676,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-/*
- *    @implemented
- */
-HWND APIENTRY
-NtUserWindowFromPoint(LONG X, LONG Y)
-{
-   POINT pt;
-   HWND Ret;
-   PWND DesktopWindow = NULL, Window = NULL;
-   USHORT hittest;
-   DECLARE_RETURN(HWND);
-   USER_REFERENCE_ENTRY Ref;
-
-   TRACE("Enter NtUserWindowFromPoint\n");
-   UserEnterExclusive();
-
-   if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
-   {
-      //PTHREADINFO pti;
-
-      pt.x = X;
-      pt.y = Y;
-
-      //hmm... threads live on desktops thus we have a reference on the desktop and indirectly the desktop window
-      //its possible this referencing is useless, thou it shouldnt hurt...
-      UserRefObjectCo(DesktopWindow, &Ref);
-
-      //pti = PsGetCurrentThreadWin32Thread();
-      Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest);
-
-      if(Window)
-      {
-         Ret = Window->head.h;
-
-         RETURN( Ret);
-      }
-   }
-
-   RETURN( NULL);
-
-CLEANUP:
-   if (Window) UserDereferenceObject(Window);
-   if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
-
-   TRACE("Leave NtUserWindowFromPoint, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-
-}
-
-
 /*
  * NtUserDefSetText
  *
index cc35e51..0e66486 100644 (file)
@@ -24,6 +24,9 @@ DBG_DEFAULT_CHANNEL(UserWinpos);
     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
 
 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
+#define PLACE_MIN               0x0001
+#define PLACE_MAX               0x0002
+#define PLACE_RECT              0x0004
 
 /* FUNCTIONS *****************************************************************/
 
@@ -125,6 +128,25 @@ done:
    if (WndTo) UserDerefObjectCo(WndTo);
 }
 
+BOOL
+FASTCALL
+WinPosShowIconTitle( PWND pWnd, BOOL bShow )
+{
+   HICON hIcon;
+   if (!pWnd->pcls || pWnd->fnid == FNID_DESKTOP) return FALSE;
+   if (!hIcon) hIcon = pWnd->pcls->hIconSm;
+   if (!hIcon) hIcon = pWnd->pcls->hIcon;
+   if (!hIcon) return FALSE;
+
+   if ( bShow )
+   {
+      // FIXME: Draw ICON!
+   }
+   else if (hIcon)
+      return FALSE;
+
+   return FALSE;
+}
 
 UINT
 FASTCALL
@@ -163,9 +185,13 @@ co_WinPosArrangeIconicWindows(PWND parent)
          USER_REFERENCE_ENTRY Ref;
          UserRefObjectCo(Child, &Ref);
 
-         co_WinPosSetWindowPos(Child, 0, x + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2,
-                               y - yspacing - UserGetSystemMetrics(SM_CYICON) / 2
-                               , 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+         co_WinPosSetWindowPos( Child,
+                                0,
+                                x + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2,
+                                y - yspacing - UserGetSystemMetrics(SM_CYICON) / 2,
+                                0,
+                                0,
+                                SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
 
          UserDerefObjectCo(Child);
 
@@ -186,64 +212,320 @@ co_WinPosArrangeIconicWindows(PWND parent)
 static VOID FASTCALL
 WinPosFindIconPos(PWND Window, POINT *Pos)
 {
-   ERR("WinPosFindIconPos FIXME!\n");
+   RECT rect, rectParent;
+   PWND pwndChild, pwndParent;
+   HRGN hrgn, tmp;
+   int xspacing, yspacing;
+
+   pwndParent = Window->spwndParent;
+   if (pwndParent == UserGetDesktopWindow())
+   {
+      /* ReactOS doesn't support iconic minimize to desktop */
+      Pos->x = Pos->y = -32000;
+      return;
+   }
+
+   IntGetClientRect( pwndParent, &rectParent );
+   if ((Pos->x >= rectParent.left) && (Pos->x + UserGetSystemMetrics(SM_CXICON) < rectParent.right) &&
+       (Pos->y >= rectParent.top) && (Pos->y + UserGetSystemMetrics(SM_CYICON) < rectParent.bottom))
+      return;  /* The icon already has a suitable position */
+
+   xspacing = UserGetSystemMetrics(SM_CXICONSPACING);
+   yspacing = UserGetSystemMetrics(SM_CYICONSPACING);
+
+   /* Check if another icon already occupies this spot */
+   /* FIXME: this is completely inefficient */
+
+   hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
+   tmp = IntSysCreateRectRgn( 0, 0, 0, 0 );
+   for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext)
+   {
+        if (pwndChild == Window) continue;
+        if ((pwndChild->style & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE))
+            continue;
+        if ( pwndChild->spwndParent )
+        {
+            PWND Parent = pwndChild->spwndParent;
+            rect.left = rect.top = 0;
+            rect.right = Parent->rcWindow.right - Parent->rcWindow.left;
+            rect.bottom = Parent->rcWindow.bottom - Parent->rcWindow.top;
+            NtGdiSetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom );
+            NtGdiCombineRgn( hrgn, hrgn, tmp, RGN_OR );
+        }
+   }
+   GreDeleteObject( tmp );
+
+   for (rect.bottom = rectParent.bottom; rect.bottom >= yspacing; rect.bottom -= yspacing)
+   {
+       for (rect.left = rectParent.left; rect.left <= rectParent.right - xspacing; rect.left += xspacing)
+       {
+            rect.right = rect.left + xspacing;
+            rect.top = rect.bottom - yspacing;
+            if (!IntRectInRegion( hrgn, &rect ))
+            {
+                /* No window was found, so it's OK for us */
+                Pos->x = rect.left + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2;
+                Pos->y = rect.top + (yspacing - UserGetSystemMetrics(SM_CYICON)) / 2;
+                GreDeleteObject( hrgn );
+                return;
+            }
+        }
+   }
+   GreDeleteObject( hrgn );
+   Pos->x = Pos->y = 0;
+   return;
 }
 
 VOID FASTCALL
-WinPosInitInternalPos(PWND Wnd, POINT *pt, RECTL *RestoreRect)
+WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect)
 {
-    PWND Parent;
-    UINT XInc, YInc;
+   POINT Size;
+   RECTL Rect = *RestoreRect;
+
+   if (Wnd->spwndParent != UserGetDesktopWindow())
+   {
+      RECTL_vOffsetRect(&Rect,
+                        -Wnd->spwndParent->rcClient.left,
+                        -Wnd->spwndParent->rcClient.top);
+   }
+
+   Size.x = Rect.left;
+   Size.y = Rect.top;
 
    if (!Wnd->InternalPosInitialized)
    {
-      RECTL WorkArea;
+      // FIXME: Use check point Atom..
+      Wnd->InternalPos.flags = 0;
+      Wnd->InternalPos.MaxPos.x  = Wnd->InternalPos.MaxPos.y  = -1;
+      Wnd->InternalPos.IconPos.x = Wnd->InternalPos.IconPos.y = -1;
+      Wnd->InternalPos.NormalRect = Rect;
+      Wnd->InternalPosInitialized = TRUE;
+   }
+
+   if (Wnd->style & WS_MINIMIZE)
+   {
+      Wnd->InternalPos.IconPos = Size;
+      Wnd->InternalPos.flags |= WPF_MININIT;
+   }
+   else if (Wnd->style & WS_MAXIMIZE)
+   {
+      Wnd->InternalPos.flags |= WPF_MAXINIT;
 
-      Parent = Wnd->spwndParent;
-      if(Parent)
+      if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd )
       {
-         if(IntIsDesktopWindow(Parent))
-             UserSystemParametersInfo(SPI_GETWORKAREA, 0, &WorkArea, 0);
+         if (Wnd->state & WNDS_MAXIMIZESTOMONITOR)
+         {
+            Wnd->InternalPos.flags &= ~WPF_MAXINIT;
+            Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1; 
+         }
          else
-            WorkArea = Parent->rcClient;
+         {
+            RECTL WorkArea;
+            PMONITOR pmonitor = IntMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY );
+
+            // FIXME: support DPI aware, rcWorkDPI/Real etc..
+            if (!(Wnd->style & WS_MAXIMIZEBOX) || (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen)
+               WorkArea = pmonitor->rcMonitor;
+            else
+               WorkArea = pmonitor->rcWork;
+
+            Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left;
+            Wnd->InternalPos.MaxPos.y = Rect.top  - WorkArea.top;
+            TRACE("WinPosIP 2 X %d Y %d\n",Wnd->InternalPos.MaxPos.x,Wnd->InternalPos.MaxPos.y);
+         }
       }
       else
-         UserSystemParametersInfo(SPI_GETWORKAREA, 0, &WorkArea, 0);
+         Wnd->InternalPos.MaxPos = Size;
+   }
+   else
+   {
+      Wnd->InternalPos.NormalRect = Rect;
+   }
+}
 
-      Wnd->InternalPos.NormalRect = Wnd->rcWindow;
-      IntGetWindowBorderMeasures(Wnd, &XInc, &YInc);
-      Wnd->InternalPos.MaxPos.x = WorkArea.left - XInc;
-      Wnd->InternalPos.MaxPos.y = WorkArea.top - YInc;
-      Wnd->InternalPos.IconPos.x = WorkArea.left;
-      Wnd->InternalPos.IconPos.y = WorkArea.bottom - UserGetSystemMetrics(SM_CYMINIMIZED);
+BOOL
+FASTCALL
+IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
+{
+   if (!Wnd) return FALSE;
 
-      Wnd->InternalPosInitialized = TRUE;
+   if(lpwndpl->length != sizeof(WINDOWPLACEMENT))
+   {
+      return FALSE;
    }
-   if (Wnd->style & WS_MINIMIZE)
+
+   lpwndpl->flags = 0;
+
+   WinPosInitInternalPos(Wnd, &Wnd->rcWindow);
+
+   lpwndpl->showCmd = SW_HIDE;
+
+   if ( Wnd->style & WS_MINIMIZE )
+      lpwndpl->showCmd = SW_SHOWMINIMIZED;
+   else
+      lpwndpl->showCmd = ( Wnd->style & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
+
+   lpwndpl->rcNormalPosition = Wnd->InternalPos.NormalRect;
+
+   if (Wnd->InternalPos.flags & WPF_MININIT) // Return if it was set!
    {
-      Wnd->InternalPos.IconPos = *pt;
+      lpwndpl->ptMinPosition.x = Wnd->InternalPos.IconPos.x;
+      lpwndpl->ptMinPosition.y = Wnd->InternalPos.IconPos.y;
    }
-   else if (Wnd->style & WS_MAXIMIZE)
+   else
+      lpwndpl->ptMinPosition.x = lpwndpl->ptMinPosition.y = -1;
+
+   if ( Wnd->InternalPos.flags & WPF_MAXINIT && // Return if set and not maximized to monitor!
+        !(Wnd->state & WNDS_MAXIMIZESTOMONITOR))
+   {
+      lpwndpl->ptMaxPosition.x = Wnd->InternalPos.MaxPos.x;
+      lpwndpl->ptMaxPosition.y = Wnd->InternalPos.MaxPos.y;
+   }
+   else
+      lpwndpl->ptMaxPosition.x = lpwndpl->ptMaxPosition.y = -1;
+
+   if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd &&
+       !(Wnd->ExStyle & WS_EX_TOOLWINDOW))
+   {
+      PMONITOR pmonitor = IntMonitorFromRect(&lpwndpl->rcNormalPosition, MONITOR_DEFAULTTOPRIMARY );
+
+      // FIXME: support DPI aware, rcWorkDPI/Real etc..
+      if (Wnd->InternalPos.flags & WPF_MININIT)
+      {
+         lpwndpl->ptMinPosition.x -= (pmonitor->rcWork.left - pmonitor->rcMonitor.left);
+         lpwndpl->ptMinPosition.y -= (pmonitor->rcWork.top - pmonitor->rcMonitor.top);
+      }
+      RECTL_vOffsetRect(&lpwndpl->rcNormalPosition,
+                         pmonitor->rcMonitor.left - pmonitor->rcWork.left,
+                         pmonitor->rcMonitor.top  - pmonitor->rcWork.top);
+   }
+
+   if ( Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED || Wnd->style & WS_MAXIMIZE )
+      lpwndpl->flags |= WPF_RESTORETOMAXIMIZED;
+
+   if ( ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) && Wnd->InternalPos.flags & WPF_SETMINPOSITION)
+      lpwndpl->flags |= WPF_SETMINPOSITION;
+
+   return TRUE;
+}
+
+/* make sure the specified rect is visible on screen */
+static void make_rect_onscreen( RECT *rect )
+{
+    PMONITOR pmonitor = IntMonitorFromRect( rect, MONITOR_DEFAULTTONEAREST ); // Wine uses this.
+
+    //  FIXME: support DPI aware, rcWorkDPI/Real etc..
+    if (!pmonitor) return;
+    /* FIXME: map coordinates from rcWork to rcMonitor */
+    if (rect->right <= pmonitor->rcWork.left)
+    {
+        rect->right += pmonitor->rcWork.left - rect->left;
+        rect->left = pmonitor->rcWork.left;
+    }
+    else if (rect->left >= pmonitor->rcWork.right)
+    {
+        rect->left += pmonitor->rcWork.right - rect->right;
+        rect->right = pmonitor->rcWork.right;
+    }
+    if (rect->bottom <= pmonitor->rcWork.top)
+    {
+        rect->bottom += pmonitor->rcWork.top - rect->top;
+        rect->top = pmonitor->rcWork.top;
+    }
+    else if (rect->top >= pmonitor->rcWork.bottom)
+    {
+        rect->top += pmonitor->rcWork.bottom - rect->bottom;
+        rect->bottom = pmonitor->rcWork.bottom;
+    }
+}
+
+/* make sure the specified point is visible on screen */
+static void make_point_onscreen( POINT *pt )
+{
+    RECT rect;
+
+    RECTL_vSetRect( &rect, pt->x, pt->y, pt->x + 1, pt->y + 1 );
+    make_rect_onscreen( &rect );
+    pt->x = rect.left;
+    pt->y = rect.top;
+}
+
+BOOL FASTCALL
+IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags)
+{
+   BOOL sAsync;
+   UINT SWP_Flags;
+
+   if ( Flags & PLACE_MIN) make_point_onscreen( &wpl->ptMinPosition );
+   if ( Flags & PLACE_MAX) make_point_onscreen( &wpl->ptMaxPosition );
+   if ( Flags & PLACE_RECT) make_rect_onscreen( &wpl->rcNormalPosition );
+
+   if (!Wnd || Wnd == Wnd->head.rpdesk->pDeskInfo->spwnd) return FALSE;
+
+   if ( Flags & PLACE_MIN ) Wnd->InternalPos.IconPos = wpl->ptMinPosition;
+   if ( Flags & PLACE_MAX ) Wnd->InternalPos.MaxPos = wpl->ptMaxPosition;
+   if ( Flags & PLACE_RECT) Wnd->InternalPos.NormalRect = wpl->rcNormalPosition;
+
+   SWP_Flags = SWP_NOZORDER | SWP_NOACTIVATE | ((wpl->flags & WPF_ASYNCWINDOWPLACEMENT) ? SWP_ASYNCWINDOWPOS : 0);
+
+   if (Wnd->style & WS_MINIMIZE )
+   {
+      if (Flags & PLACE_MIN)
+      {
+         co_WinPosSetWindowPos(Wnd, HWND_TOP,
+                               wpl->ptMinPosition.x, wpl->ptMinPosition.y, 0, 0,
+                               SWP_NOSIZE | SWP_Flags);
+         Wnd->InternalPos.flags |= WPF_MININIT;
+      }
+   }
+   else if (Wnd->style & WS_MAXIMIZE )
+   {
+      if (Flags & PLACE_MAX)
+      {
+         co_WinPosSetWindowPos(Wnd, HWND_TOP,
+                               wpl->ptMaxPosition.x, wpl->ptMaxPosition.y, 0, 0,
+                               SWP_NOSIZE | SWP_Flags);
+         Wnd->InternalPos.flags |= WPF_MAXINIT;
+      }
+   }
+   else if (Flags & PLACE_RECT)
    {
-      Wnd->InternalPos.MaxPos = *pt;
+      co_WinPosSetWindowPos(Wnd, HWND_TOP,
+                            wpl->rcNormalPosition.left, wpl->rcNormalPosition.top,
+                            wpl->rcNormalPosition.right - wpl->rcNormalPosition.left,
+                            wpl->rcNormalPosition.bottom - wpl->rcNormalPosition.top,
+                            SWP_Flags);
    }
-   else if (RestoreRect != NULL)
+
+   sAsync = (Wnd->head.pti->MessageQueue != gptiCurrent->MessageQueue && wpl->flags & WPF_ASYNCWINDOWPLACEMENT);
+
+   if ( sAsync )
+      co_IntSendMessageNoWait( UserHMGetHandle(Wnd), WM_ASYNC_SHOWWINDOW, wpl->showCmd, 0 );
+   else
+      co_WinPosShowWindow(Wnd, wpl->showCmd);
+
+   if ( Wnd->style & WS_MINIMIZE && !sAsync )
    {
-      Wnd->InternalPos.NormalRect = *RestoreRect;
+      if ( wpl->flags & WPF_SETMINPOSITION )
+         Wnd->InternalPos.flags |= WPF_SETMINPOSITION;
+
+      if ( wpl->flags & WPF_RESTORETOMAXIMIZED )
+         Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
    }
+   return TRUE;
 }
 
 UINT FASTCALL
 co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
 {
    POINT Size;
+   WINDOWPLACEMENT wpl;
    UINT SwpFlags = 0;
 
    ASSERT_REFS_CO(Wnd);
 
-   Size.x = Wnd->rcWindow.left;
-   Size.y = Wnd->rcWindow.top;
-   WinPosInitInternalPos(Wnd, &Size, &Wnd->rcWindow);
+   wpl.length = sizeof(wpl);
+   IntGetWindowPlacement( Wnd, &wpl );
 
    if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
    {
@@ -252,6 +534,8 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
    }
       if (Wnd->style & WS_MINIMIZE)
       {
+         if (ShowFlag == SW_MINIMIZE) return SWP_NOSIZE | SWP_NOMOVE;
+
          if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
          {
             return(SWP_NOSIZE | SWP_NOMOVE);
@@ -264,18 +548,18 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
             {
                if (Wnd->style & WS_MAXIMIZE)
                {
-                  Wnd->state2 |= WNDS2_MAXIMIZEBUTTONDOWN;
+                  Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
                   Wnd->style &= ~WS_MAXIMIZE;
                }
                else
                {
-                  Wnd->state2 &= ~WNDS2_MAXIMIZEBUTTONDOWN;
+                  Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
                }
                co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
                                    RDW_NOINTERNALPAINT);
                Wnd->style |= WS_MINIMIZE;
-               WinPosFindIconPos(Wnd, &Wnd->InternalPos.IconPos);
-               RECTL_vSetRect(NewPos, Wnd->InternalPos.IconPos.x, Wnd->InternalPos.IconPos.y,
+               WinPosFindIconPos(Wnd, &wpl.ptMinPosition);
+               RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
                              UserGetSystemMetrics(SM_CXMINIMIZED),
                              UserGetSystemMetrics(SM_CYMINIMIZED));
                SwpFlags |= SWP_NOCOPYBITS;
@@ -284,17 +568,16 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
 
          case SW_MAXIMIZE:
             {
-               co_WinPosGetMinMaxInfo(Wnd, &Size, &Wnd->InternalPos.MaxPos,
-                                      NULL, NULL);
+               co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
+
                TRACE("Maximize: %d,%d %dx%d\n",
-                      Wnd->InternalPos.MaxPos.x, Wnd->InternalPos.MaxPos.y, Size.x, Size.y);
+                      wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
                if (Wnd->style & WS_MINIMIZE)
                {
                   Wnd->style &= ~WS_MINIMIZE;
                }
                Wnd->style |= WS_MAXIMIZE;
-               RECTL_vSetRect(NewPos, Wnd->InternalPos.MaxPos.x, Wnd->InternalPos.MaxPos.y,
-                             Size.x, Size.y);
+               RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
                break;
             }
 
@@ -303,18 +586,17 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
                if (Wnd->style & WS_MINIMIZE)
                {
                   Wnd->style &= ~WS_MINIMIZE;
-                  if (Wnd->state2 & WNDS2_MAXIMIZEBUTTONDOWN)
+                  if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED)
                   {
-                     co_WinPosGetMinMaxInfo(Wnd, &Size,
-                                            &Wnd->InternalPos.MaxPos, NULL, NULL);
+                     co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
+
                      Wnd->style |= WS_MAXIMIZE;
-                     RECTL_vSetRect(NewPos, Wnd->InternalPos.MaxPos.x,
-                                   Wnd->InternalPos.MaxPos.y, Size.x, Size.y);
+                     RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
                      break;
                   }
                   else
                   {
-                     *NewPos = Wnd->InternalPos.NormalRect;
+                     *NewPos = wpl.rcNormalPosition;
                      NewPos->right -= NewPos->left;
                      NewPos->bottom -= NewPos->top;
                      break;
@@ -327,8 +609,8 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
                      return 0;
                   }
                   Wnd->style &= ~WS_MAXIMIZE;
-                  Wnd->state2 &= ~WNDS2_MAXIMIZEBUTTONDOWN;
-                  *NewPos = Wnd->InternalPos.NormalRect;
+                  Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
+                  *NewPos = wpl.rcNormalPosition;
                   NewPos->right -= NewPos->left;
                   NewPos->bottom -= NewPos->top;
                   break;
@@ -455,7 +737,7 @@ co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
     MinMax.ptMaxPosition.x = -xinc;
     MinMax.ptMaxPosition.y = -yinc;
 
-    if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos;
+   if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos;
 
     co_IntSendMessage(Window->head.h, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
 
@@ -946,6 +1228,7 @@ co_WinPosSetWindowPos(
    if ( Window->head.h == IntGetDesktopWindow() &&
         Window->head.pti->pEThread->ThreadsProcess != PsGetCurrentProcess())
    {
+      ERR("Desktop Window...\n");
       return FALSE;
    }
    bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y);
@@ -1337,7 +1620,7 @@ co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
    ASSERT_REFS_CO(Window);
 
    *ClientRect = *WindowRect;
-   Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
+   Result = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
 
    FixClientRect(ClientRect, WindowRect);
 
@@ -1347,8 +1630,12 @@ co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
 void FASTCALL
 co_WinPosSendSizeMove(PWND Wnd)
 {
+    RECTL Rect;
+    LPARAM lParam;
     WPARAM wParam = SIZE_RESTORED;
 
+    IntGetClientRect(Wnd, &Rect);
+
     Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS;
     if (Wnd->style & WS_MAXIMIZE)
     {
@@ -1359,14 +1646,14 @@ co_WinPosSendSizeMove(PWND Wnd)
         wParam = SIZE_MINIMIZED;
     }
 
-    co_IntSendMessageNoWait(Wnd->head.h, WM_SIZE, wParam,
-                        MAKELONG(Wnd->rcClient.right -
-                                 Wnd->rcClient.left,
-                                 Wnd->rcClient.bottom -
-                                 Wnd->rcClient.top));
-    co_IntSendMessageNoWait(Wnd->head.h, WM_MOVE, 0,
-                        MAKELONG(Wnd->rcClient.left,
-                                 Wnd->rcClient.top));
+    co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top));
+
+    if (Wnd->spwndParent == UserGetDesktopWindow()) // Wnd->spwndParent->fnid != FNID_DESKTOP )
+       lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top);
+    else
+       lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top);
+
+    co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam);
     IntEngWindowChanged(Wnd, WOC_RGN_CLIENT);
 }
 
@@ -1454,7 +1741,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd)
          break;
 
       case SW_SHOWNOACTIVATE:
-         Wnd->state2 &= ~WNDS2_MAXIMIZEBUTTONDOWN;
+         Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
          //Swp |= SWP_NOZORDER;
          Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
          /* Fall through. */
@@ -1734,7 +2021,7 @@ END:
     return retvalue;
 }
 
-BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp )
+BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync )
 {
     PSMWP pDWP;
     PCVR winpos;
@@ -1764,13 +2051,30 @@ BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp )
 
         UserRefObjectCo(pwnd, &Ref);
 
-        res = co_WinPosSetWindowPos( pwnd,
-                                     winpos->pos.hwndInsertAfter,
-                                     winpos->pos.x,
-                                     winpos->pos.y,
-                                     winpos->pos.cx,
-                                     winpos->pos.cy,
-                                     winpos->pos.flags);
+        if ( sAsync )
+        {
+           LRESULT lRes;
+           PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP);
+           if ( ppos )
+           {
+              *ppos = winpos->pos;
+              /* Yes it's a pointer inside Win32k! */
+              lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos);
+              /* We handle this the same way as Event Hooks and Hooks. */
+              if ( -1 == (int) lRes )
+              {
+                 ExFreePoolWithTag(ppos, USERTAG_SWP);
+              }
+           }
+        }
+        else
+           res = co_WinPosSetWindowPos( pwnd,
+                                        winpos->pos.hwndInsertAfter,
+                                        winpos->pos.x,
+                                        winpos->pos.y,
+                                        winpos->pos.cx,
+                                        winpos->pos.cy,
+                                        winpos->pos.flags);
 
         UserDerefObjectCo(pwnd);
     }
@@ -1780,6 +2084,7 @@ BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp )
     return res;
 }
 
+
 /*
  * @implemented
  */
@@ -1856,7 +2161,7 @@ NtUserEndDeferWindowPosEx(HDWP WinPosInfo,
    BOOL Ret;
    TRACE("Enter NtUserEndDeferWindowPosEx\n");
    UserEnterExclusive();
-   Ret = IntEndDeferWindowPosEx(WinPosInfo);
+   Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1);
    TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret);
    UserLeave();
    return Ret;
@@ -1920,6 +2225,128 @@ Exit:
    return Ret;
 }
 
+/*
+ * @implemented
+ */
+DWORD APIENTRY
+NtUserGetInternalWindowPos( HWND hWnd,
+                            LPRECT rectWnd,
+                            LPPOINT ptIcon)
+{
+   PWND Window;
+   DWORD Ret = 0;
+   BOOL Hit = FALSE;
+   WINDOWPLACEMENT wndpl;
+
+   UserEnterShared();
+
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+      Hit = FALSE;
+      goto Exit;
+   }
+
+   _SEH2_TRY
+   {
+       if(rectWnd)
+       {
+          ProbeForWrite(rectWnd,
+                        sizeof(RECT),
+                        1);
+       }
+       if(ptIcon)
+       {
+          ProbeForWrite(ptIcon,
+                        sizeof(POINT),
+                        1);
+       }
+
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+       SetLastNtError(_SEH2_GetExceptionCode());
+       Hit = TRUE;
+   }
+   _SEH2_END;
+
+   wndpl.length = sizeof(WINDOWPLACEMENT);
+
+   if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
+   {
+      _SEH2_TRY
+      {
+          if (rectWnd)
+          {
+             RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
+          }
+          if (ptIcon)
+          {
+             RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
+          }
+
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+          SetLastNtError(_SEH2_GetExceptionCode());
+          Hit = TRUE;
+      }
+      _SEH2_END;
+
+      if (!Hit) Ret = wndpl.showCmd;
+   }
+Exit:
+   UserLeave();
+   return Ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL APIENTRY
+NtUserGetWindowPlacement(HWND hWnd,
+                         WINDOWPLACEMENT *lpwndpl)
+{
+   PWND Wnd;
+   WINDOWPLACEMENT Safepl;
+   NTSTATUS Status;
+   DECLARE_RETURN(BOOL);
+
+   TRACE("Enter NtUserGetWindowPlacement\n");
+   UserEnterShared();
+
+   if (!(Wnd = UserGetWindowObject(hWnd)))
+   {
+      RETURN( FALSE);
+   }
+
+   Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
+   if(!NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      RETURN( FALSE);
+   }
+   if(Safepl.length != sizeof(WINDOWPLACEMENT))
+   {
+      RETURN( FALSE);
+   }
+
+   IntGetWindowPlacement(Wnd, &Safepl);
+
+   Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
+   if(!NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      RETURN( FALSE);
+   }
+
+   RETURN( TRUE);
+
+CLEANUP:
+   TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
 DWORD
 APIENTRY
 NtUserMinMaximize(
@@ -2085,8 +2512,9 @@ NtUserSetWindowRgn(
       if (GreIsHandleValid(hRgn))
       {
          hrgnCopy = IntSysCreateRectRgn(0, 0, 0, 0);
-
-         NtGdiCombineRgn(hrgnCopy, hRgn, 0, RGN_COPY);
+      /* The coordinates of a window's window region are relative to the
+         upper-left corner of the window, not the client area of the window. */
+         NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY);
       }
       else
          RETURN( 0);
@@ -2096,9 +2524,6 @@ NtUserSetWindowRgn(
       hrgnCopy = NULL;
    }
 
-   /* Delete the region passed by the caller */
-   GreDeleteObject(hRgn);
-
    if (Window->hrgnClip)
    {
       /* Delete no longer needed region handle */
@@ -2123,6 +2548,81 @@ CLEANUP:
    END_CLEANUP;
 }
 
+/*
+ * @implemented
+ */
+DWORD APIENTRY
+NtUserSetInternalWindowPos(
+   HWND    hwnd,
+   UINT    showCmd,
+   LPRECT  lprect,
+   LPPOINT lppt)
+{
+   WINDOWPLACEMENT wndpl;
+   UINT flags;
+   PWND Wnd;
+   RECT rect;
+   POINT pt = {0};
+   DECLARE_RETURN(BOOL);
+   USER_REFERENCE_ENTRY Ref;
+
+   TRACE("Enter NtUserSetWindowPlacement\n");
+   UserEnterExclusive();
+
+   if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME:
+         Wnd == IntGetDesktopWindow() ||     // pWnd->fnid == FNID_DESKTOP
+         Wnd == IntGetMessageWindow() )      // pWnd->fnid == FNID_MESSAGEWND
+   {
+      RETURN( FALSE);
+   }
+
+   _SEH2_TRY
+   {
+      if (lppt)
+      {
+         ProbeForRead(lppt, sizeof(POINT), 1);
+         RtlCopyMemory(&pt, lppt, sizeof(POINT));
+      }
+      if (lprect)
+      {
+         ProbeForRead(lprect, sizeof(RECT), 1);
+         RtlCopyMemory(&rect, lprect, sizeof(RECT));
+      }
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      SetLastNtError(_SEH2_GetExceptionCode());
+      _SEH2_YIELD(RETURN( FALSE));
+   }
+   _SEH2_END
+
+   wndpl.length  = sizeof(wndpl);
+   wndpl.showCmd = showCmd;
+   wndpl.flags = flags = 0;
+
+   if ( lppt )
+   {
+      flags |= PLACE_MIN;
+      wndpl.flags |= WPF_SETMINPOSITION;
+      wndpl.ptMinPosition = pt;
+   }
+   if ( lprect )
+   {
+      flags |= PLACE_RECT;
+      wndpl.rcNormalPosition = rect;
+   }
+
+   UserRefObjectCo(Wnd, &Ref);
+   IntSetWindowPlacement(Wnd, &wndpl, flags);
+   UserDerefObjectCo(Wnd);
+   RETURN(TRUE);
+
+CLEANUP:
+   TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
 /*
  * @implemented
  */
@@ -2132,6 +2632,7 @@ NtUserSetWindowPlacement(HWND hWnd,
 {
    PWND Wnd;
    WINDOWPLACEMENT Safepl;
+   UINT Flags;
    DECLARE_RETURN(BOOL);
    USER_REFERENCE_ENTRY Ref;
 
@@ -2162,25 +2663,10 @@ NtUserSetWindowPlacement(HWND hWnd,
       RETURN( FALSE);
    }
 
+   Flags = PLACE_MAX | PLACE_RECT;
+   if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN;
    UserRefObjectCo(Wnd, &Ref);
-
-   if ((Wnd->style & (WS_MAXIMIZE | WS_MINIMIZE)) == 0)
-   {
-      co_WinPosSetWindowPos(Wnd, NULL,
-                            Safepl.rcNormalPosition.left, Safepl.rcNormalPosition.top,
-                            Safepl.rcNormalPosition.right - Safepl.rcNormalPosition.left,
-                            Safepl.rcNormalPosition.bottom - Safepl.rcNormalPosition.top,
-                            SWP_NOZORDER | SWP_NOACTIVATE);
-   }
-
-   /* FIXME - change window status */
-   co_WinPosShowWindow(Wnd, Safepl.showCmd);
-
-   Wnd->InternalPosInitialized = TRUE;
-   Wnd->InternalPos.NormalRect = Safepl.rcNormalPosition;
-   Wnd->InternalPos.IconPos = Safepl.ptMinPosition;
-   Wnd->InternalPos.MaxPos = Safepl.ptMaxPosition;
-
+   IntSetWindowPlacement(Wnd, &Safepl, Flags);
    UserDerefObjectCo(Wnd);
    RETURN(TRUE);
 
@@ -2191,17 +2677,43 @@ CLEANUP:
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL APIENTRY
 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow)
 {
-#if 0
-   STUB
-   return 0;
-#else
-   return NtUserShowWindow(hWnd, nCmdShow);
-#endif
+   PWND Window;
+   BOOL ret;
+   DECLARE_RETURN(BOOL);
+   USER_REFERENCE_ENTRY Ref;
+
+   TRACE("Enter NtUserShowWindowAsync\n");
+   UserEnterExclusive();
+
+   if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
+         Window == IntGetDesktopWindow() ||     // pWnd->fnid == FNID_DESKTOP
+         Window == IntGetMessageWindow() )      // pWnd->fnid == FNID_MESSAGEWND
+   {
+      RETURN(FALSE);
+   }
+
+   if ( nCmdShow > SW_MAX )
+   {
+      EngSetLastError(ERROR_INVALID_PARAMETER);
+      RETURN(FALSE);
+   }
+
+   UserRefObjectCo(Window, &Ref);
+   ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 );
+   UserDerefObjectCo(Window);
+   if (-1 == (int) ret || !ret) ret = FALSE;
+
+   RETURN(ret);
+
+CLEANUP:
+   TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 /*
@@ -2243,56 +2755,54 @@ CLEANUP:
    END_CLEANUP;
 }
 
-//// Ugly NtUser API ////
-BOOL
-APIENTRY
-NtUserGetMinMaxInfo(
-   HWND hWnd,
-   MINMAXINFO *MinMaxInfo,
-   BOOL SendMessage)
+
+/*
+ *    @implemented
+ */
+HWND APIENTRY
+NtUserWindowFromPoint(LONG X, LONG Y)
 {
-   POINT Size;
-   PWND Window = NULL;
-   MINMAXINFO SafeMinMax;
-   NTSTATUS Status;
-   BOOL ret;
+   POINT pt;
+   HWND Ret;
+   PWND DesktopWindow = NULL, Window = NULL;
+   USHORT hittest;
+   DECLARE_RETURN(HWND);
    USER_REFERENCE_ENTRY Ref;
 
-   TRACE("Enter NtUserGetMinMaxInfo\n");
+   TRACE("Enter NtUserWindowFromPoint\n");
    UserEnterExclusive();
 
-   if(!(Window = UserGetWindowObject(hWnd)))
+   if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
    {
-      ret = FALSE;
-      goto cleanup;
-   }
+      //PTHREADINFO pti;
 
-   UserRefObjectCo(Window, &Ref);
+      pt.x = X;
+      pt.y = Y;
 
-   Size.x = Window->rcWindow.left;
-   Size.y = Window->rcWindow.top;
-   WinPosInitInternalPos(Window, &Size,
-                         &Window->rcWindow);
+      //hmm... threads live on desktops thus we have a reference on the desktop and indirectly the desktop window
+      //its possible this referencing is useless, thou it shouldnt hurt...
+      UserRefObjectCo(DesktopWindow, &Ref);
 
-   co_WinPosGetMinMaxInfo(Window, &SafeMinMax.ptMaxSize, &SafeMinMax.ptMaxPosition,
-                          &SafeMinMax.ptMinTrackSize, &SafeMinMax.ptMaxTrackSize);
+      //pti = PsGetCurrentThreadWin32Thread();
+      Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest);
 
-   Status = MmCopyToCaller(MinMaxInfo, &SafeMinMax, sizeof(MINMAXINFO));
-   if(!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      ret = FALSE;
-      goto cleanup;
+      if(Window)
+      {
+         Ret = Window->head.h;
+
+         RETURN( Ret);
+      }
    }
 
-   ret = TRUE;
+   RETURN( NULL);
 
-cleanup:
-   if (Window) UserDerefObjectCo(Window);
+CLEANUP:
+   if (Window) UserDereferenceObject(Window);
+   if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
 
-   TRACE("Leave NtUserGetMinMaxInfo, ret=%i\n", ret);
+   TRACE("Leave NtUserWindowFromPoint, ret=%i\n",_ret_);
    UserLeave();
-   return ret;
+   END_CLEANUP;
 }
 
 /* EOF */
index e797b04..e5330ea 100644 (file)
@@ -683,7 +683,6 @@ NtGdiOffsetWindowOrgEx                  4
 #
 NtUserBuildMenuItemList                 4
 NtUserGetMenuDefaultItem                3
-NtUserGetMinMaxInfo                     3
 NtUserGetMonitorInfo                    2
 NtUserMenuInfo                          3
 NtUserMenuItemInfo                      5
index 1bd678d..ce06f56 100644 (file)
@@ -683,7 +683,6 @@ SVC_(GdiOffsetWindowOrgEx, 4)
 
 SVC_(UserBuildMenuItemList, 4)
 SVC_(UserGetMenuDefaultItem, 3)
-SVC_(UserGetMinMaxInfo, 3)
 SVC_(UserGetMonitorInfo, 2)
 SVC_(UserMenuInfo, 3)
 SVC_(UserMenuItemInfo, 5)