[Win32k]
[reactos.git] / reactos / win32ss / user / ntuser / window.c
index dbe7421..b5386d7 100644 (file)
@@ -9,6 +9,8 @@
 #include <win32k.h>
 DBG_DEFAULT_CHANNEL(UserWnd);
 
+INT gNestedWindowLimit = 50;
+
 /* HELPER FUNCTIONS ***********************************************************/
 
 BOOL FASTCALL UserUpdateUiState(PWND Wnd, WPARAM wParam)
@@ -86,6 +88,12 @@ PWND FASTCALL VerifyWnd(PWND pWnd)
    return pWnd;
 }
 
+PWND FASTCALL ValidateHwndNoErr(HWND hWnd)
+{
+   if (hWnd) return (PWND)UserGetObjectNoErr(gHandleTable, hWnd, TYPE_WINDOW);
+   return NULL;
+}
+
 /* Temp HACK */
 PWND FASTCALL UserGetWindowObject(HWND hWnd)
 {
@@ -97,7 +105,7 @@ PWND FASTCALL UserGetWindowObject(HWND hWnd)
       return NULL;
    }
 
-   Window = (PWND)UserGetObject(gHandleTable, hWnd, otWindow);
+   Window = (PWND)UserGetObject(gHandleTable, hWnd, TYPE_WINDOW);
    if (!Window || 0 != (Window->state & WNDS_DESTROYED))
    {
       EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
@@ -115,7 +123,12 @@ IntSetStyle( PWND pwnd, ULONG set_bits, ULONG clear_bits )
     styleNew = (pwnd->style | set_bits) & ~clear_bits;
     if (styleNew == styleOld) return styleNew;
     pwnd->style = styleNew;
-    if ((styleOld ^ styleNew) & WS_VISIBLE) DceResetActiveDCEs( pwnd );
+    if ((styleOld ^ styleNew) & WS_VISIBLE) // State Change.
+    {
+       if (styleOld & WS_VISIBLE) pwnd->head.pti->cVisWindows--; 
+       if (styleNew & WS_VISIBLE) pwnd->head.pti->cVisWindows++;
+       DceResetActiveDCEs( pwnd );
+    }
     return styleOld;
 }
 
@@ -141,7 +154,9 @@ IntIsWindow(HWND hWnd)
    PWND Window;
 
    if (!(Window = UserGetWindowObject(hWnd)))
+   {
       return FALSE;
+   }
 
    return TRUE;
 }
@@ -149,21 +164,16 @@ IntIsWindow(HWND hWnd)
 BOOL FASTCALL
 IntIsWindowVisible(PWND Wnd)
 {
-   BOOL Ret = TRUE;
-   do
+   PWND Temp = Wnd;
+   for (;;)
    {
-      if (!(Wnd->style & WS_VISIBLE))
-      {
-         Ret = FALSE;
-         break;
-      }
-      if (Wnd->spwndParent != NULL)
-         Wnd = Wnd->spwndParent;
-      else
-         break;
+      if (!Temp) return TRUE;
+      if (!(Temp->style & WS_VISIBLE)) break;
+      if (Temp->style & WS_MINIMIZE && Temp != Wnd) break;
+      if (Temp->fnid == FNID_DESKTOP) return TRUE;
+      Temp = Temp->spwndParent;
    }
-   while (Wnd != NULL);
-   return Ret;
+   return FALSE;
 }
 
 PWND FASTCALL
@@ -211,6 +221,7 @@ IntEnableWindow( HWND hWnd, BOOL bEnable )
        /* Remove keyboard focus from that window if it had focus */
        if (hWnd == IntGetThreadFocusWindow())
        {
+          TRACE("IntEnableWindow SF NULL\n");
           co_UserSetFocus(NULL);
        }
        IntSetStyle( pWnd, WS_DISABLED, 0 );
@@ -263,6 +274,94 @@ IntWinListChildren(PWND Window)
    return List;
 }
 
+PWND FASTCALL
+IntGetNonChildAncestor(PWND pWnd)
+{
+   while(pWnd && (pWnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+      pWnd = pWnd->spwndParent;
+   return pWnd;
+}
+
+BOOL FASTCALL
+IntIsTopLevelWindow(PWND pWnd)
+{
+   if ( pWnd->spwndParent &&
+        pWnd->spwndParent == co_GetDesktopWindow(pWnd) ) return TRUE;
+   return FALSE;
+}
+
+BOOL FASTCALL
+IntValidateOwnerDepth(PWND Wnd, PWND Owner)
+{
+   INT Depth = 1;
+   for (;;)
+   {
+      if ( !Owner ) return gNestedWindowLimit >= Depth;
+      if (Owner == Wnd) break;
+      Owner = Owner->spwndOwner;
+      Depth++;
+   }
+   return FALSE;
+}
+
+HWND FASTCALL
+IntGetWindow(HWND hWnd,
+          UINT uCmd)
+{
+    PWND Wnd, FoundWnd;
+    HWND Ret = NULL;
+
+    Wnd = ValidateHwndNoErr(hWnd);
+    if (!Wnd)
+        return NULL;
+
+    FoundWnd = NULL;
+    switch (uCmd)
+    {
+            case GW_OWNER:
+                if (Wnd->spwndOwner != NULL)
+                    FoundWnd = Wnd->spwndOwner;
+                break;
+
+            case GW_HWNDFIRST:
+                if(Wnd->spwndParent != NULL)
+                {
+                    FoundWnd = Wnd->spwndParent;
+                    if (FoundWnd->spwndChild != NULL)
+                        FoundWnd = FoundWnd->spwndChild;
+                }
+                break;
+            case GW_HWNDNEXT:
+                if (Wnd->spwndNext != NULL)
+                    FoundWnd = Wnd->spwndNext;
+                break;
+
+            case GW_HWNDPREV:
+                if (Wnd->spwndPrev != NULL)
+                    FoundWnd = Wnd->spwndPrev;
+                break;
+   
+            case GW_CHILD:
+                if (Wnd->spwndChild != NULL)
+                    FoundWnd = Wnd->spwndChild;
+                break;
+
+            case GW_HWNDLAST:
+                FoundWnd = Wnd;
+                while ( FoundWnd->spwndNext != NULL)
+                    FoundWnd = FoundWnd->spwndNext;
+                break;
+
+            default:
+                Wnd = NULL;
+                break;
+    }
+
+    if (FoundWnd != NULL)
+        Ret = UserHMGetHandle(FoundWnd);
+    return Ret;
+}
+
 /***********************************************************************
  *           IntSendDestroyMsg
  */
@@ -291,7 +390,7 @@ static void IntSendDestroyMsg(HWND hWnd)
 
       if (!Window->spwndOwner && !IntGetParent(Window))
       {
-         co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM) hWnd);
+         co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM) hWnd, 0);
       }
 
 //      UserDerefObjectCo(Window);
@@ -360,7 +459,7 @@ UserFreeWindowInfo(PTHREADINFO ti, PWND Wnd)
    }
 
 //    DesktopHeapFree(Wnd->head.rpdesk, Wnd);
-//    WindowObject->Wnd = NULL;
+//    WindowObject->hWnd = NULL;
 }
 
 /***********************************************************************
@@ -380,7 +479,7 @@ static LRESULT co_UserFreeWindow(PWND Window,
    HWND *Children;
    HWND *ChildHandle;
    PWND Child;
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    BOOLEAN BelongsToThreadData;
 
    ASSERT(Window);
@@ -392,6 +491,7 @@ static LRESULT co_UserFreeWindow(PWND Window,
    }
    Window->state2 |= WNDS2_INDESTROY;
    Window->style &= ~WS_VISIBLE;
+   Window->head.pti->cVisWindows--;
 
    IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
 
@@ -429,7 +529,7 @@ static LRESULT co_UserFreeWindow(PWND Window,
             UserDereferenceObject(Child);
          }
       }
-      ExFreePool(Children);
+      ExFreePoolWithTag(Children, USERTAG_WINDOWLIST);
    }
 
    if(SendMessages)
@@ -453,8 +553,6 @@ static LRESULT co_UserFreeWindow(PWND Window,
    /* flush the message queue */
    MsqRemoveWindowMessagesFromQueue(Window);
 
-   IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
-
    /* from now on no messages can be sent to this window anymore */
    Window->state |= WNDS_DESTROYED;
    Window->fnid |= FNID_FREED;
@@ -509,8 +607,15 @@ static LRESULT co_UserFreeWindow(PWND Window,
 
    IntUnlinkWindow(Window);
 
+   if (Window->PropListItems)
+   {
+      IntRemoveWindowProp(Window);
+      TRACE("Window->PropListItems %d\n",Window->PropListItems);
+      ASSERT(Window->PropListItems==0);
+   }
+
    UserReferenceObject(Window);
-   UserDeleteObject(Window->head.h, otWindow);
+   UserDeleteObject(Window->head.h, TYPE_WINDOW);
 
    IntDestroyScrollBars(Window);
 
@@ -526,6 +631,7 @@ static LRESULT co_UserFreeWindow(PWND Window,
       GreDeleteObject(Window->hrgnClip);
       Window->hrgnClip = NULL;
    }
+   Window->head.pti->cWindows--;
 
 //   ASSERT(Window != NULL);
    UserFreeWindowInfo(Window->head.pti, Window);
@@ -617,7 +723,7 @@ IntSetWindowProc(PWND pWnd,
 
    if (IsCallProcHandle(NewWndProc))
    {
-      CallProc = UserGetObject(gHandleTable, NewWndProc, otCallProc);
+      CallProc = UserGetObject(gHandleTable, NewWndProc, TYPE_CALLPROC);
       if (CallProc)
       {  // Reset new WndProc.
          NewWndProc = CallProc->pfnClientPrevious;
@@ -686,10 +792,11 @@ IntSetMenu(
    HMENU Menu,
    BOOL *Changed)
 {
-   PMENU_OBJECT OldMenu, NewMenu = NULL;
+   PMENU OldMenu, NewMenu = NULL;
 
    if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
    {
+      ERR("SetMenu: Invalid handle 0x%p!\n",UserHMGetHandle(Wnd));
       EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
       return FALSE;
    }
@@ -703,7 +810,7 @@ IntSetMenu(
    if (Wnd->IDMenu)
    {
       OldMenu = IntGetMenuObject((HMENU) Wnd->IDMenu);
-      ASSERT(NULL == OldMenu || OldMenu->MenuInfo.Wnd == Wnd->head.h);
+      ASSERT(NULL == OldMenu || OldMenu->hWnd == Wnd->head.h);
    }
    else
    {
@@ -722,7 +829,7 @@ IntSetMenu(
          EngSetLastError(ERROR_INVALID_MENU_HANDLE);
          return FALSE;
       }
-      if (NULL != NewMenu->MenuInfo.Wnd)
+      if (NULL != NewMenu->hWnd)
       {
          /* Can't use the same menu for two windows */
          if (NULL != OldMenu)
@@ -738,12 +845,12 @@ IntSetMenu(
    Wnd->IDMenu = (UINT) Menu;
    if (NULL != NewMenu)
    {
-      NewMenu->MenuInfo.Wnd = Wnd->head.h;
+      NewMenu->hWnd = Wnd->head.h;
       IntReleaseMenuObject(NewMenu);
    }
    if (NULL != OldMenu)
    {
-      OldMenu->MenuInfo.Wnd = NULL;
+      OldMenu->hWnd = NULL;
       IntReleaseMenuObject(OldMenu);
    }
 
@@ -768,7 +875,7 @@ co_DestroyThreadWindows(struct _ETHREAD *Thread)
       Current = WThread->WindowListHead.Flink;
       Wnd = CONTAINING_RECORD(Current, WND, ThreadListEntry);
 
-      TRACE("thread cleanup: while destroy wnds, wnd=0x%x\n",Wnd);
+      TRACE("thread cleanup: while destroy wnds, wnd=%p\n", Wnd);
 
       /* Window removes itself from the list */
 
@@ -782,19 +889,21 @@ co_DestroyThreadWindows(struct _ETHREAD *Thread)
       UserRefObjectCo(Wnd, &Ref); // FIXME: Temp HACK??
       if (!co_UserDestroyWindow(Wnd))
       {
-         ERR("Unable to destroy window 0x%x at thread cleanup... This is _VERY_ bad!\n", Wnd);
+         ERR("Unable to destroy window %p at thread cleanup... This is _VERY_ bad!\n", Wnd);
       }
       UserDerefObjectCo(Wnd); // FIXME: Temp HACK??
    }
 }
 
-PMENU_OBJECT FASTCALL
+PMENU FASTCALL
 IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
 {
-   PMENU_OBJECT Menu, NewMenu = NULL, SysMenu = NULL, ret = NULL;
+   PMENU Menu, NewMenu = NULL, SysMenu = NULL, ret = NULL;
    PTHREADINFO W32Thread;
    HMENU hNewMenu, hSysMenu;
-   ROSMENUITEMINFO ItemInfo;
+   ROSMENUITEMINFO ItemInfoSet = {0};
+   ROSMENUITEMINFO ItemInfo = {0};
+   UNICODE_STRING MenuName;
 
    if(bRevert)
    {
@@ -822,10 +931,10 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
 
          NewMenu = IntCloneMenu(Menu);
          if(NewMenu)
-         {
-            Window->SystemMenu = NewMenu->MenuInfo.Self;
-            NewMenu->MenuInfo.Flags |= MF_SYSMENU;
-            NewMenu->MenuInfo.Wnd = Window->head.h;
+         {  // Use spmenuSys
+            Window->SystemMenu = NewMenu->head.h;
+            NewMenu->fFlags |= MNF_SYSDESKMN;
+            NewMenu->hWnd = Window->head.h;
             ret = NewMenu;
             //IntReleaseMenuObject(NewMenu);
          }
@@ -843,11 +952,23 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
             UserDestroyMenu(hSysMenu);
             return NULL;
          }
-         SysMenu->MenuInfo.Flags |= MF_SYSMENU;
-         SysMenu->MenuInfo.Wnd = Window->head.h;
-         hNewMenu = co_IntLoadSysMenuTemplate();
+         SysMenu->fFlags |= MNF_SYSDESKMN;
+         SysMenu->hWnd = Window->head.h;
+         //hNewMenu = co_IntLoadSysMenuTemplate();
+         //if ( Window->ExStyle & WS_EX_MDICHILD )
+         //{
+         //   RtlInitUnicodeString( &MenuName, L"SYSMENUMDI");
+         //   hNewMenu = co_IntCallLoadMenu( hModClient, &MenuName);
+         //}
+         //else
+         {
+            RtlInitUnicodeString( &MenuName, L"SYSMENU");
+            hNewMenu = co_IntCallLoadMenu( hModClient, &MenuName);
+            //ERR("%wZ\n",&MenuName);
+         }
          if(!hNewMenu)
          {
+            ERR("No Menu!!\n");
             IntReleaseMenuObject(SysMenu);
             UserDestroyMenu(hSysMenu);
             return NULL;
@@ -860,23 +981,42 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
             return NULL;
          }
 
+         // Do the rest in here.
+
+         Menu->fFlags |= MNS_CHECKORBMP | MNF_SYSDESKMN | MNF_POPUP;
+
+         ItemInfoSet.cbSize = sizeof( MENUITEMINFOW);
+         ItemInfoSet.fMask = MIIM_BITMAP;
+         ItemInfoSet.hbmpItem = HBMMENU_POPUP_CLOSE;
+         IntMenuItemInfo(Menu, SC_CLOSE, FALSE, &ItemInfoSet, TRUE, NULL);
+         ItemInfoSet.hbmpItem = HBMMENU_POPUP_RESTORE;
+         IntMenuItemInfo(Menu, SC_RESTORE, FALSE, &ItemInfoSet, TRUE, NULL);
+         ItemInfoSet.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
+         IntMenuItemInfo(Menu, SC_MAXIMIZE, FALSE, &ItemInfoSet, TRUE, NULL);
+         ItemInfoSet.hbmpItem = HBMMENU_POPUP_MINIMIZE;
+         IntMenuItemInfo(Menu, SC_MINIMIZE, FALSE, &ItemInfoSet, TRUE, NULL);
+
          NewMenu = IntCloneMenu(Menu);
          if(NewMenu)
          {
-            NewMenu->MenuInfo.Flags |= MF_SYSMENU | MF_POPUP;
+            NewMenu->fFlags |= MNF_SYSDESKMN | MNF_POPUP;
+            // Do not set MNS_CHECKORBMP it breaks menus, also original code destroyed the style anyway.
             IntReleaseMenuObject(NewMenu);
             UserSetMenuDefaultItem(NewMenu, SC_CLOSE, FALSE);
 
+            if (Window->pcls->style & CS_NOCLOSE)
+               IntRemoveMenuItem(NewMenu, SC_CLOSE, MF_BYCOMMAND, TRUE);
+
             ItemInfo.cbSize = sizeof(MENUITEMINFOW);
             ItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU;
-            ItemInfo.fType = MF_POPUP;
+            ItemInfo.fType = 0;
             ItemInfo.fState = MFS_ENABLED;
             ItemInfo.dwTypeData = NULL;
             ItemInfo.cch = 0;
-            ItemInfo.hSubMenu = NewMenu->MenuInfo.Self;
-            IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo);
+            ItemInfo.hSubMenu = NewMenu->head.h;
+            IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo, NULL);
 
-            Window->SystemMenu = SysMenu->MenuInfo.Self;
+            Window->SystemMenu = SysMenu->head.h;
 
             ret = SysMenu;
          }
@@ -1031,6 +1171,38 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
             }
         }
     }
+    Wnd->ExStyle2 |= WS_EX2_LINKED;
+}
+
+VOID FASTCALL
+IntProcessOwnerSwap(PWND Wnd, PWND WndNewOwner, PWND WndOldOwner)
+{
+   if (WndOldOwner)
+   {
+      if (Wnd->head.pti != WndOldOwner->head.pti)
+      {
+         if (!WndNewOwner ||
+              Wnd->head.pti == WndNewOwner->head.pti ||
+              WndOldOwner->head.pti != WndNewOwner->head.pti )
+         {
+            //ERR("ProcessOwnerSwap Old out.\n");
+            UserAttachThreadInput(Wnd->head.pti, WndOldOwner->head.pti, FALSE);
+         }
+      }
+   }
+   if (WndNewOwner)
+   {
+      if (Wnd->head.pti != WndNewOwner->head.pti)
+      {
+         if (!WndOldOwner ||
+              WndOldOwner->head.pti != WndNewOwner->head.pti )
+         {
+            //ERR("ProcessOwnerSwap New in.\n");
+            UserAttachThreadInput(Wnd->head.pti, WndNewOwner->head.pti, TRUE);
+         }
+      }
+   }
+   // FIXME: System Tray checks.
 }
 
 HWND FASTCALL
@@ -1045,17 +1217,38 @@ IntSetOwner(HWND hWnd, HWND hWndNewOwner)
 
    WndOldOwner = Wnd->spwndOwner;
 
-   ret = WndOldOwner ? WndOldOwner->head.h : 0;
+   ret = WndOldOwner ? UserHMGetHandle(WndOldOwner) : 0;
+   WndNewOwner = UserGetWindowObject(hWndNewOwner);
+
+   if (!WndNewOwner && hWndNewOwner)
+   {
+      EngSetLastError(ERROR_INVALID_PARAMETER);
+      ret = NULL;
+      goto Error;
+   }
+
+   /* if parent belongs to a different thread and the window isn't */
+   /* top-level, attach the two threads */
+   IntProcessOwnerSwap(Wnd, WndNewOwner, WndOldOwner);
 
-   if((WndNewOwner = UserGetWindowObject(hWndNewOwner)))
+   if (IntValidateOwnerDepth(Wnd, WndNewOwner))
    {
-       Wnd->spwndOwner= WndNewOwner;
+      if (WndNewOwner)
+      {
+         Wnd->spwndOwner= WndNewOwner;
+      }
+      else
+      {
+         Wnd->spwndOwner = NULL;
+      }
    }
    else
    {
-       Wnd->spwndOwner = NULL;
+      IntProcessOwnerSwap(Wnd, WndOldOwner, WndNewOwner);
+      EngSetLastError(ERROR_INVALID_PARAMETER);
+      ret = NULL;
    }
-
+Error:
    UserDereferenceObject(Wnd);
    return ret;
 }
@@ -1082,6 +1275,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
    /* Some applications try to set a child as a parent */
    if (IntIsChildWindow(Wnd, WndNewParent))
    {
+      TRACE("IntSetParent try to set a child as a parent.\n");
       EngSetLastError( ERROR_INVALID_PARAMETER );
       return NULL;
    }
@@ -1092,6 +1286,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
    {
       if (Wnd == pWndExam)
       {
+         TRACE("IntSetParent Failed Test for set parent to parent!\n");
          EngSetLastError(ERROR_INVALID_PARAMETER);
          return NULL;
       }
@@ -1106,28 +1301,34 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
 
    /* Window must belong to current process */
    if (Wnd->head.pti->ppi != PsGetCurrentProcessWin32Process())
+   {
+      ERR("IntSetParent Window must belong to current process!\n");
       return NULL;
+   }
 
    WndOldParent = Wnd->spwndParent;
 
-   if ( WndOldParent && 
+   if ( WndOldParent &&
         WndOldParent->ExStyle & WS_EX_LAYOUTRTL)
       pt.x = Wnd->rcWindow.right;
    else
       pt.x = Wnd->rcWindow.left;
    pt.y = Wnd->rcWindow.top;
 
+   IntScreenToClient(WndOldParent, &pt);
+
    if (WndOldParent) UserReferenceObject(WndOldParent); /* Caller must deref */
 
    if (WndNewParent != WndOldParent)
    {
       /* Unlink the window from the siblings list */
       IntUnlinkWindow(Wnd);
+      Wnd->ExStyle2 &= ~WS_EX2_LINKED;
 
       /* Set the new parent */
       Wnd->spwndParent = WndNewParent;
 
-      if ( Wnd->style & WS_CHILD && 
+      if ( Wnd->style & WS_CHILD &&
            Wnd->spwndOwner &&
            Wnd->spwndOwner->ExStyle & WS_EX_TOPMOST )
       {
@@ -1142,6 +1343,35 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
 
    }
 
+   if ( WndNewParent == co_GetDesktopWindow(Wnd) &&
+       !(Wnd->style & WS_CLIPSIBLINGS) )
+   {
+      Wnd->style |= WS_CLIPSIBLINGS;
+      DceResetActiveDCEs(Wnd);
+   }
+
+   /* if parent belongs to a different thread and the window isn't */
+   /* top-level, attach the two threads */
+   if ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
+   {
+      if ( Wnd->spwndParent != co_GetDesktopWindow(Wnd))
+      {
+         if (Wnd->head.pti != WndOldParent->head.pti)
+         {
+            //ERR("SetParent Old out.\n");
+            UserAttachThreadInput(Wnd->head.pti, WndOldParent->head.pti, FALSE);
+         }
+      }
+      if ( WndNewParent != co_GetDesktopWindow(Wnd))
+      {
+         if (Wnd->head.pti != WndNewParent->head.pti)
+         {
+            //ERR("SetParent New in.\n");
+            UserAttachThreadInput(Wnd->head.pti, WndNewParent->head.pti, TRUE);
+         }
+      }
+   }
+
    if (WndOldParent == UserGetMessageWindow() || WndNewParent == UserGetMessageWindow())
       swFlags |= SWP_NOACTIVATE;
 
@@ -1151,10 +1381,11 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
     * in the z-order and send the expected WM_WINDOWPOSCHANGING and
     * WM_WINDOWPOSCHANGED notification messages.
     */
+   //ERR("IntSetParent SetWindowPos 1\n");
    co_WinPosSetWindowPos( Wnd,
                          (0 == (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOP : HWND_TOPMOST),
                           pt.x, pt.y, 0, 0, swFlags);
-
+   //ERR("IntSetParent SetWindowPos 2 X %d Y %d\n",pt.x, pt.y);
    if (WasVisible) co_WinPosShowWindow(Wnd, SW_SHOWNORMAL);
 
    return WndOldParent;
@@ -1175,6 +1406,7 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent)
 
    if (hWndChild == IntGetDesktopWindow())
    {
+      ERR("UserSetParent Access Denied!\n");
       EngSetLastError(ERROR_ACCESS_DENIED);
       return( NULL);
    }
@@ -1183,6 +1415,7 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent)
    {
       if (!(WndParent = UserGetWindowObject(hWndNewParent)))
       {
+         ERR("UserSetParent Bad New Parent!\n");
          return( NULL);
       }
    }
@@ -1196,6 +1429,7 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent)
 
    if (!(Wnd = UserGetWindowObject(hWndChild)))
    {
+      ERR("UserSetParent Bad Child!\n");
       return( NULL);
    }
 
@@ -1217,15 +1451,15 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent)
 }
 
 BOOL FASTCALL
-IntSetSystemMenu(PWND Window, PMENU_OBJECT Menu)
+IntSetSystemMenu(PWND Window, PMENU Menu)
 {
-   PMENU_OBJECT OldMenu;
+   PMENU OldMenu;
    if(Window->SystemMenu)
    {
       OldMenu = IntGetMenuObject(Window->SystemMenu);
       if(OldMenu)
       {
-         OldMenu->MenuInfo.Flags &= ~ MF_SYSMENU;
+         OldMenu->fFlags &= ~ MNF_SYSDESKMN;
          IntReleaseMenuObject(OldMenu);
       }
    }
@@ -1233,10 +1467,10 @@ IntSetSystemMenu(PWND Window, PMENU_OBJECT Menu)
    if(Menu)
    {
       /* FIXME: Check window style, propably return FALSE? */
-      Window->SystemMenu = Menu->MenuInfo.Self;
-      Menu->MenuInfo.Flags |= MF_SYSMENU;
+      Window->SystemMenu = Menu->head.h;
+      Menu->fFlags |= MNF_SYSDESKMN;
    }
-   else
+   else // Use spmenuSys too!
       Window->SystemMenu = (HMENU)0;
 
    return TRUE;
@@ -1540,24 +1774,26 @@ IntFixWindowCoordinates(CREATESTRUCTW* Cs, PWND ParentWindow, DWORD* dwShowMode)
 
 /* Allocates and initializes a window */
 PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
-                                        PLARGE_STRING WindowName,
-                                        PCLS Class,
-                                        PWND ParentWindow,
-                                        PWND OwnerWindow,
-                                        PVOID acbiBuffer)
+                              PLARGE_STRING WindowName,
+                              PCLS Class,
+                              PWND ParentWindow,
+                              PWND OwnerWindow,
+                              PVOID acbiBuffer,
+                              PDESKTOP pdeskCreated)
 {
    PWND pWnd = NULL;
    HWND hWnd;
    PTHREADINFO pti = NULL;
-   PMENU_OBJECT SystemMenu;
+   PMENU SystemMenu;
    BOOL MenuChanged;
    BOOL bUnicodeWindow;
 
-   pti = PsGetCurrentThreadWin32Thread();
+   pti = pdeskCreated ? gptiDesktopThread : GetW32ThreadInfo();
 
    if (!(Cs->dwExStyle & WS_EX_LAYOUTRTL))
-   {
-      if (ParentWindow)
+   {      // Need both here for wine win.c test_CreateWindow.
+      //if (Cs->hwndParent && ParentWindow)
+      if (ParentWindow) // It breaks more tests..... WIP.
       {
          if ( (Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD &&
               ParentWindow->ExStyle & WS_EX_LAYOUTRTL &&
@@ -1573,8 +1809,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
          */
          if ( Class->fnid != FNID_DIALOG )
          {
-            PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
-            if (ppi->dwLayout & LAYOUT_RTL)
+            if (pti->ppi->dwLayout & LAYOUT_RTL)
             {
                Cs->dwExStyle |= WS_EX_LAYOUTRTL;
             }
@@ -1596,9 +1831,10 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
 
    /* Allocate the new window */
    pWnd = (PWND) UserCreateObject( gHandleTable,
-                                   pti->rpdesk,
+                                   pdeskCreated ? pdeskCreated : pti->rpdesk,
+                                   pti,
                                   (PHANDLE)&hWnd,
-                                   otWindow,
+                                   TYPE_WINDOW,
                                    sizeof(WND) + Class->cbwndExtra);
 
    if (!pWnd)
@@ -1606,13 +1842,14 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
       goto AllocError;
    }
 
-   TRACE("Created object with handle %X\n", hWnd);
+   TRACE("Created window object with handle %p\n", hWnd);
 
-   if (NULL == pti->rpdesk->DesktopWindow)
+   if (pdeskCreated && pdeskCreated->DesktopWindow == NULL )
    {  /* HACK: Helper for win32csr/desktopbg.c */
       /* If there is no desktop window yet, we must be creating it */
-      pti->rpdesk->DesktopWindow = hWnd;
-      pti->rpdesk->pDeskInfo->spwnd = pWnd;
+      TRACE("CreateWindow setting desktop.\n");
+      pdeskCreated->DesktopWindow = hWnd;
+      pdeskCreated->pDeskInfo->spwnd = pWnd;
    }
 
    /*
@@ -1633,13 +1870,23 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    pWnd->InternalPos.MaxPos.x  = pWnd->InternalPos.MaxPos.y  = -1;
    pWnd->InternalPos.IconPos.x = pWnd->InternalPos.IconPos.y = -1;
 
-   IntReferenceMessageQueue(pWnd->head.pti->MessageQueue);
    if (pWnd->spwndParent != NULL && Cs->hwndParent != 0)
    {
        pWnd->HideFocus = pWnd->spwndParent->HideFocus;
        pWnd->HideAccel = pWnd->spwndParent->HideAccel;
    }
 
+   pWnd->head.pti->cWindows++;
+
+   if (Class->hIcon && !Class->hIconSm)
+   {
+      Class->hIconSmIntern = co_IntCopyImage( Class->hIcon, IMAGE_ICON,
+                                              UserGetSystemMetrics( SM_CXSMICON ),
+                                              UserGetSystemMetrics( SM_CYSMICON ), 0 );
+      TRACE("IntCreateWindow hIconSmIntern %p\n",Class->hIconSmIntern);
+      Class->CSF_flags |= CSF_CACHEDSMICON;
+   }
+
    if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC)
       pWnd->state |= WNDS_SERVERSIDEWINDOWPROC;
 
@@ -1715,7 +1962,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
       if (!CallProc)
       {
          EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-         ERR("Warning: Unable to create CallProc for edit control. Control may not operate correctly! hwnd %x\n",hWnd);
+         ERR("Warning: Unable to create CallProc for edit control. Control may not operate correctly! hwnd %p\n", hWnd);
       }
       else
       {
@@ -1770,8 +2017,8 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    {
       SystemMenu = IntGetSystemMenu(pWnd, TRUE, TRUE);
       if(SystemMenu)
-      {
-         pWnd->SystemMenu = SystemMenu->MenuInfo.Self;
+      {  //    spmenuSys
+         pWnd->SystemMenu = SystemMenu->head.h;
          IntReleaseMenuObject(SystemMenu);
       }
    }
@@ -1803,6 +2050,32 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    else // Not a child
       pWnd->IDMenu = (UINT) Cs->hMenu;
 
+
+   if ( ParentWindow &&
+        ParentWindow != ParentWindow->head.rpdesk->spwndMessage &&
+        ParentWindow != ParentWindow->head.rpdesk->pDeskInfo->spwnd )
+   {
+       PWND Owner = IntGetNonChildAncestor(ParentWindow);
+
+       if (!IntValidateOwnerDepth(pWnd, Owner))
+       {
+          EngSetLastError(ERROR_INVALID_PARAMETER);
+          goto Error;
+       }
+       if ( pWnd->spwndOwner &&
+            pWnd->spwndOwner->ExStyle & WS_EX_TOPMOST )
+       {
+          pWnd->ExStyle |= WS_EX_TOPMOST;
+       }
+       if ( pWnd->spwndOwner &&
+            Class->atomClassName != gpsi->atomSysClass[ICLS_IME] &&
+            pti != pWnd->spwndOwner->head.pti)
+       {
+          //ERR("CreateWindow Owner in.\n");
+          UserAttachThreadInput(pti, pWnd->spwndOwner->head.pti, TRUE);
+       }
+   }
+
    /* Insert the window into the thread's window list. */
    InsertTailList (&pti->WindowListHead, &pWnd->ThreadListEntry);
 
@@ -1820,10 +2093,10 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
 
 AllocError:
    ERR("IntCreateWindow Allocation Error.\n");
+   SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
+Error:
    if(pWnd)
       UserDereferenceObject(pWnd);
-
-   SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
    return NULL;
 }
 
@@ -1842,7 +2115,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    PWINSTATION_OBJECT WinSta;
    PCLS Class = NULL;
    SIZE Size;
-   POINT MaxPos;
+   POINT MaxSize, MaxPos, MinTrack, MaxTrack;
    CBT_CREATEWNDW * pCbtCreate;
    LRESULT Result;
    USER_REFERENCE_ENTRY ParentRef, Ref;
@@ -1866,7 +2139,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    pCbtCreate = NULL;
 
    /* Get the class and reference it */
-   Class = IntGetAndReferenceClass(ClassName, Cs->hInstance);
+   Class = IntGetAndReferenceClass(ClassName, Cs->hInstance, FALSE);
    if(!Class)
    {
        ERR("Failed to find class %wZ\n", ClassName);
@@ -1874,12 +2147,12 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    }
 
    /* Now find the parent and the owner window */
-   hWndParent = IntGetDesktopWindow();
+   hWndParent = pti->rpdesk->pDeskInfo->spwnd->head.h;
    hWndOwner = NULL;
 
     if (Cs->hwndParent == HWND_MESSAGE)
     {
-        Cs->hwndParent = hWndParent = IntGetMessageWindow();
+        Cs->hwndParent = hWndParent = pti->rpdesk->spwndMessage->head.h;
     }
     else if (Cs->hwndParent)
     {
@@ -1915,7 +2188,8 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
                             Class,
                             ParentWindow,
                             OwnerWindow,
-                            acbiBuffer);
+                            acbiBuffer,
+                            NULL);
    if(!Window)
    {
        ERR("IntCreateWindow failed!\n");
@@ -2038,14 +2312,21 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    Cs->lpszName = (LPCWSTR) WindowName;
    Cs->lpszClass = (LPCWSTR) ClassName;
 
+   if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
+   {
+      if (ParentWindow != co_GetDesktopWindow(Window))
+      {
+         Cs->x += ParentWindow->rcClient.left;
+         Cs->y += ParentWindow->rcClient.top; 
+      }
+   }
+
    /* Send the WM_GETMINMAXINFO message */
    Size.cx = Cs->cx;
    Size.cy = Cs->cy;
 
    if ((Cs->style & WS_THICKFRAME) || !(Cs->style & (WS_POPUP | WS_CHILD)))
    {
-      POINT MaxSize, MaxPos, MinTrack, MaxTrack;
-
       co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack, &MaxTrack);
       if (Size.cx > MaxTrack.x) Size.cx = MaxTrack.x;
       if (Size.cy > MaxTrack.y) Size.cy = MaxTrack.y;
@@ -2057,6 +2338,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    Window->rcWindow.top = Cs->y;
    Window->rcWindow.right = Cs->x + Size.cx;
    Window->rcWindow.bottom = Cs->y + Size.cy;
+/*
    if (0 != (Window->style & WS_CHILD) && ParentWindow)
    {
 //      ERR("co_UserCreateWindowEx(): Offset rcWindow\n");
@@ -2064,6 +2346,18 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
                         ParentWindow->rcClient.left,
                         ParentWindow->rcClient.top);
    }
+*/
+   /* correct child window coordinates if mirroring on parent is enabled */
+   if (ParentWindow != NULL)
+   {
+      if ( ((Cs->style & WS_CHILD) == WS_CHILD) && 
+          ((ParentWindow->ExStyle & WS_EX_LAYOUTRTL) ==  WS_EX_LAYOUTRTL))
+      {
+          Window->rcWindow.right = ParentWindow->rcClient.right - (Window->rcWindow.left - ParentWindow->rcClient.left);
+          Window->rcWindow.left = Window->rcWindow.right - Size.cx;
+      }
+   }
+
    Window->rcClient = Window->rcWindow;
 
    /* Link the window */
@@ -2076,6 +2370,24 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
           IntLinkHwnd(Window, hwndInsertAfter);
    }
 
+   if (!(Window->state2 & WNDS2_WIN31COMPAT))
+   {
+      if (Class->style & CS_PARENTDC && !(ParentWindow->style & WS_CLIPCHILDREN))
+         Window->style &= ~(WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+   }
+
+   if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+   {
+      if ( !IntIsTopLevelWindow(Window) )
+      {
+         if (pti != Window->spwndParent->head.pti)
+         {
+            //ERR("CreateWindow Parent in.\n");
+            UserAttachThreadInput(pti, Window->spwndParent->head.pti, TRUE);
+         }
+      }
+   }
+
    /* Send the NCCREATE message */
    Result = co_IntSendMessage(UserHMGetHandle(Window), WM_NCCREATE, 0, (LPARAM) Cs);
    if (!Result)
@@ -2085,14 +2397,19 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    }
 
    /* Send the WM_NCCALCSIZE message */
+   {
+  // RECT rc;
    MaxPos.x = Window->rcWindow.left;
    MaxPos.y = Window->rcWindow.top;
 
    Result = co_WinPosGetNonClientSize(Window, &Window->rcWindow, &Window->rcClient);
+   //rc = Window->rcWindow;
+   //Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM)&rc);
+   //Window->rcClient = rc;
 
    RECTL_vOffsetRect(&Window->rcWindow, MaxPos.x - Window->rcWindow.left,
                                      MaxPos.y - Window->rcWindow.top);
-
+   }
 
    /* Send the WM_CREATE message. */
    Result = co_IntSendMessage(UserHMGetHandle(Window), WM_CREATE, 0, (LPARAM) Cs);
@@ -2137,7 +2454,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    /* Notify the shell that a new window was created */
    if ((!hWndParent) && (!hWndOwner))
    {
-      co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)hWnd);
+      co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)hWnd, 0);
    }
 
    /* Initialize and show the window's scrollbars */
@@ -2171,7 +2488,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
       }
    }
 
-   TRACE("co_UserCreateWindowEx(): Created window %X\n", hWnd);
+   TRACE("co_UserCreateWindowEx(): Created window %p\n", hWnd);
    ret = Window;
 
 cleanup:
@@ -2239,7 +2556,7 @@ ProbeAndCaptureLargeString(
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
             /* Cleanup and fail */
-            ExFreePool(pvBuffer);
+            ExFreePoolWithTag(pvBuffer, TAG_STRING);
             _SEH2_YIELD(return _SEH2_GetExceptionCode();)
         }
         _SEH2_END
@@ -2288,6 +2605,16 @@ NtUserCreateWindowEx(
 
     ASSERT(plstrWindowName);
 
+    if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD) 
+    {
+        /* check hMenu is valid handle */
+        if (hMenu && !ValidateHandle(hMenu, TYPE_MENU))
+        {
+            /* error is set in ValidateHandle */
+            return NULL;
+        }
+    } 
+
     /* Copy the window name to kernel mode */
     Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
     if (!NT_SUCCESS(Status))
@@ -2373,6 +2700,7 @@ cleanup:
 BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
 {
    HWND hWnd;
+   PWND pwndTemp;
    PTHREADINFO ti;
    MSG msg;
 
@@ -2384,11 +2712,14 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
    TRACE("co_UserDestroyWindow \n");
 
    /* Check for owner thread */
-   if ( (Window->head.pti->pEThread != PsGetCurrentThread()) ||
-        Window->head.pti != PsGetCurrentThreadWin32Thread() )
+   if ( Window->head.pti != PsGetCurrentThreadWin32Thread())
    {
-      EngSetLastError(ERROR_ACCESS_DENIED);
-      return FALSE;
+       /* Check if we are destroying the desktop window */
+       if (! ((Window->head.rpdesk->dwDTFlags & DF_DESTROYED) && Window == Window->head.rpdesk->pDeskInfo->spwnd))
+       {
+           EngSetLastError(ERROR_ACCESS_DENIED);
+           return FALSE;
+       }
    }
 
    /* If window was created successfully and it is hooked */
@@ -2401,6 +2732,18 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
       }
    }
 
+   if (Window->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME])
+   {
+      if ((Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD)
+      {
+         if (Window->spwndOwner)
+         {
+            //ERR("DestroyWindow Owner out.\n");
+            UserAttachThreadInput(Window->head.pti, Window->spwndOwner->head.pti, FALSE);
+         }
+      }
+   }
+
    /* Inform the parent */
    if (Window->style & WS_CHILD)
    {
@@ -2413,25 +2756,47 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
    if (!co_WinPosShowWindow(Window, SW_HIDE))
    {  // Rule #1.
       if (ti->MessageQueue->spwndActive == Window && ti->MessageQueue == IntGetFocusMessageQueue())
-      {  //ERR("DestroyWindow AOW\n");
+      {
          co_WinPosActivateOtherWindow(Window);
       }
    }
 
+   // Adjust last active.
+   if ((pwndTemp = Window->spwndOwner))
+   {
+      while (pwndTemp->spwndOwner)
+         pwndTemp = pwndTemp->spwndOwner;
+
+      if (pwndTemp->spwndLastActive == Window)
+         pwndTemp->spwndLastActive = Window->spwndOwner;
+   }
+
+   if (Window->spwndParent && IntIsWindow(Window->head.h))
+   {
+      if ((Window->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
+      {
+         if (!IntIsTopLevelWindow(Window))
+         {
+            //ERR("DestroyWindow Parent out.\n");
+            UserAttachThreadInput(Window->head.pti, Window->spwndParent->head.pti, FALSE);
+         }
+      }
+   }
+
    if (Window->head.pti->MessageQueue->spwndActive == 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;
+   if (Window->head.pti->MessageQueue->spwndCapture == Window)
+      Window->head.pti->MessageQueue->spwndCapture = NULL;
 
    /*
     * Check if this window is the Shell's Desktop Window. If so set hShellWindow to NULL
     */
 
-   if ((ti != NULL) & (ti->pDeskInfo != NULL))
+   if ((ti != NULL) && (ti->pDeskInfo != NULL))
    {
       if (ti->pDeskInfo->hShellWindow == hWnd)
       {
@@ -2491,7 +2856,7 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
                }
 
             }
-            ExFreePool(Children);
+            ExFreePoolWithTag(Children, USERTAG_WINDOWLIST);
          }
          if (! GotOne)
          {
@@ -2545,7 +2910,7 @@ NtUserDestroyWindow(HWND Wnd)
    RETURN(ret);
 
 CLEANUP:
-   TRACE("Leave NtUserDestroyWindow, ret=%i\n",_ret_);
+   TRACE("Leave NtUserDestroyWindow, ret=%u\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -2603,7 +2968,7 @@ IntFindWindow(PWND Parent,
          }
       }
       }
-      ExFreePool(List);
+      ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
    }
 
    return Ret;
@@ -2796,7 +3161,7 @@ NtUserFindWindowEx(HWND hwndParent,
                 }
 
              }
-             ExFreePool(List);
+             ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
           }
        }
        else
@@ -2825,7 +3190,7 @@ NtUserFindWindowEx(HWND hwndParent,
    RETURN( Ret);
 
 CLEANUP:
-   TRACE("Leave NtUserFindWindowEx, ret %i\n",_ret_);
+   TRACE("Leave NtUserFindWindowEx, ret %p\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -2878,8 +3243,6 @@ PWND FASTCALL UserGetAncestor(PWND Wnd, UINT Type)
 
             for (;;)
             {
-               PWND Parent;
-
                Parent = IntGetParent(WndAncestor);
 
                if (!Parent)
@@ -2924,12 +3287,45 @@ NtUserGetAncestor(HWND hWnd, UINT Type)
    RETURN(Ancestor ? Ancestor->head.h : NULL);
 
 CLEANUP:
-   TRACE("Leave NtUserGetAncestor, ret=%i\n",_ret_);
+   TRACE("Leave NtUserGetAncestor, ret=%p\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
 
-
+////
+//// ReactOS work around! Keep it the sames as in Combo.c and Controls.h
+////
+/* combo state struct */
+typedef struct
+{
+   HWND           self;
+   HWND           owner;
+   UINT           dwStyle;
+   HWND           hWndEdit;
+   HWND           hWndLBox;
+   UINT           wState;
+   HFONT          hFont;
+   RECT           textRect;
+   RECT           buttonRect;
+   RECT           droppedRect;
+   INT            droppedIndex;
+   INT            fixedOwnerDrawHeight;
+   INT            droppedWidth;   /* last two are not used unless set */
+   INT            editHeight;     /* explicitly */
+   LONG           UIState;
+} HEADCOMBO,*LPHEADCOMBO;
+
+// Window Extra data container.
+typedef struct _WND2CBOX
+{
+  WND;
+  LPHEADCOMBO pCBox;
+} WND2CBOX, *PWND2CBOX;
+
+#define CBF_BUTTONDOWN          0x0002
+////
+////
+////
 BOOL
 APIENTRY
 NtUserGetComboBoxInfo(
@@ -2937,6 +3333,9 @@ NtUserGetComboBoxInfo(
    PCOMBOBOXINFO pcbi)
 {
    PWND Wnd;
+   PPROCESSINFO ppi;
+   BOOL NotSameppi = FALSE;
+   BOOL Ret = TRUE;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserGetComboBoxInfo\n");
@@ -2962,22 +3361,95 @@ NtUserGetComboBoxInfo(
    }
    _SEH2_END;
 
+   if (pcbi->cbSize < sizeof(COMBOBOXINFO))
+   {
+      EngSetLastError(ERROR_INVALID_PARAMETER);
+      RETURN(FALSE);
+   }
+
    // Pass the user pointer, it was already probed.
-   RETURN( (BOOL) co_IntSendMessage( Wnd->head.h, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi));
+   if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_COMBOBOX]) && Wnd->fnid != FNID_COMBOBOX)
+   {
+      RETURN( (BOOL) co_IntSendMessage( Wnd->head.h, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi));
+   }
+
+   ppi = PsGetCurrentProcessWin32Process();
+   NotSameppi = ppi != Wnd->head.pti->ppi;
+   if (NotSameppi)
+   {
+      KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
+   }
+
+   _SEH2_TRY
+   {
+      LPHEADCOMBO lphc = ((PWND2CBOX)Wnd)->pCBox;
+      pcbi->rcItem = lphc->textRect;
+      pcbi->rcButton = lphc->buttonRect;
+      pcbi->stateButton = 0;
+      if (lphc->wState & CBF_BUTTONDOWN)
+         pcbi->stateButton |= STATE_SYSTEM_PRESSED;
+      if (RECTL_bIsEmptyRect(&lphc->buttonRect))
+         pcbi->stateButton |= STATE_SYSTEM_INVISIBLE;
+      pcbi->hwndCombo = lphc->self;
+      pcbi->hwndItem = lphc->hWndEdit;
+      pcbi->hwndList = lphc->hWndLBox;
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      Ret = FALSE;
+      SetLastNtError(_SEH2_GetExceptionCode());
+   }
+   _SEH2_END;
+   
+   RETURN( Ret);
 
 CLEANUP:
+   if (NotSameppi) KeDetachProcess();
    TRACE("Leave NtUserGetComboBoxInfo, ret=%i\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
 
-
+////
+//// ReactOS work around! Keep it the sames as in Listbox.c
+////
+/* Listbox structure */
+typedef struct
+{
+    HWND        self;           /* Our own window handle */
+    HWND        owner;          /* Owner window to send notifications to */
+    UINT        style;          /* Window style */
+    INT         width;          /* Window width */
+    INT         height;         /* Window height */
+    VOID       *items;          /* Array of items */
+    INT         nb_items;       /* Number of items */
+    INT         top_item;       /* Top visible item */
+    INT         selected_item;  /* Selected item */
+    INT         focus_item;     /* Item that has the focus */
+    INT         anchor_item;    /* Anchor item for extended selection */
+    INT         item_height;    /* Default item height */
+    INT         page_size;      /* Items per listbox page */
+    INT         column_width;   /* Column width for multi-column listboxes */
+} LB_DESCR;
+
+// Window Extra data container.
+typedef struct _WND2LB
+{
+  WND;
+  LB_DESCR * pLBiv;
+} WND2LB, *PWND2LB;
+////
+////
+////
 DWORD
 APIENTRY
 NtUserGetListBoxInfo(
    HWND hWnd)
 {
    PWND Wnd;
+   PPROCESSINFO ppi;
+   BOOL NotSameppi = FALSE;
+   DWORD Ret = 0;
    DECLARE_RETURN(DWORD);
 
    TRACE("Enter NtUserGetListBoxInfo\n");
@@ -2988,10 +3460,40 @@ NtUserGetListBoxInfo(
       RETURN( 0 );
    }
 
-   RETURN( (DWORD) co_IntSendMessage( Wnd->head.h, LB_GETLISTBOXINFO, 0, 0 ));
+   if ((Wnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_LISTBOX]) && Wnd->fnid != FNID_LISTBOX)
+   {
+      RETURN( (DWORD) co_IntSendMessage( Wnd->head.h, LB_GETLISTBOXINFO, 0, 0 ));
+   }
+
+   // wine lisbox:test_GetListBoxInfo lb_getlistboxinfo = 0, should not send a message!
+   ppi = PsGetCurrentProcessWin32Process();
+   NotSameppi = ppi != Wnd->head.pti->ppi;
+   if (NotSameppi)
+   {
+      KeAttachProcess(&Wnd->head.pti->ppi->peProcess->Pcb);
+   }
+
+   _SEH2_TRY
+   {
+      LB_DESCR *descr = ((PWND2LB)Wnd)->pLBiv;
+      // See Controls ListBox.c:LB_GETLISTBOXINFO must match...
+      if (descr->style & LBS_MULTICOLUMN) //// ReactOS
+         Ret = descr->page_size * descr->column_width;
+      else
+         Ret = descr->page_size;
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      Ret = 0;
+      SetLastNtError(_SEH2_GetExceptionCode());
+   }
+   _SEH2_END;
+   
+   RETURN( Ret);
 
 CLEANUP:
-   TRACE("Leave NtUserGetListBoxInfo, ret=%i\n",_ret_);
+   if (NotSameppi) KeDetachProcess();
+   TRACE("Leave NtUserGetListBoxInfo, ret=%lu\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -3036,7 +3538,7 @@ NtUserSetParent(HWND hWndChild, HWND hWndNewParent)
    RETURN( co_UserSetParent(hWndChild, hWndNewParent));
 
 CLEANUP:
-   TRACE("Leave NtUserSetParent, ret=%i\n",_ret_);
+   TRACE("Leave NtUserSetParent, ret=%p\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -3150,6 +3652,7 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
    }
 
    UserRefObjectCo(WndShell, &Ref);
+   WndShell->state2 |= WNDS2_BOTTOMMOST;
    co_WinPosSetWindowPos(WndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
 
    WinStaObject->ShellWindow = hwndShell;
@@ -3159,9 +3662,12 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
    if (ti->pDeskInfo)
    {
        ti->pDeskInfo->hShellWindow = hwndShell;
+       ti->pDeskInfo->spwndShell = WndShell;
        ti->pDeskInfo->ppiShellProcess = ti->ppi;
    }
 
+   UserRegisterHotKey(WndShell, SC_TASKLIST, MOD_CONTROL, VK_ESCAPE);
+
    UserDerefObjectCo(WndShell);
 
    ObDereferenceObject(WinStaObject);
@@ -3204,7 +3710,7 @@ HMENU APIENTRY
 NtUserGetSystemMenu(HWND hWnd, BOOL bRevert)
 {
    PWND Window;
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(HMENU);
 
    TRACE("Enter NtUserGetSystemMenu\n");
@@ -3220,10 +3726,10 @@ NtUserGetSystemMenu(HWND hWnd, BOOL bRevert)
       RETURN(NULL);
    }
 
-   RETURN(Menu->MenuInfo.Self);
+   RETURN(Menu->head.h);
 
 CLEANUP:
-   TRACE("Leave NtUserGetSystemMenu, ret=%i\n",_ret_);
+   TRACE("Leave NtUserGetSystemMenu, ret=%p\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -3240,7 +3746,7 @@ NtUserSetSystemMenu(HWND hWnd, HMENU hMenu)
 {
    BOOL Result = FALSE;
    PWND Window;
-   PMENU_OBJECT Menu;
+   PMENU Menu;
    DECLARE_RETURN(BOOL);
 
    TRACE("Enter NtUserSetSystemMenu\n");
@@ -3292,12 +3798,6 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
    LONG OldValue;
    STYLESTRUCT Style;
 
-   if (hWnd == IntGetDesktopWindow())
-   {
-      EngSetLastError(STATUS_ACCESS_DENIED);
-      return( 0);
-   }
-
    if (!(Window = UserGetWindowObject(hWnd)))
    {
       return( 0);
@@ -3367,6 +3867,12 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
             else
                Window->ExStyle &= ~WS_EX_WINDOWEDGE;
 
+            if ((Style.styleOld ^ Style.styleNew) & WS_VISIBLE)
+            {
+               if (Style.styleOld & WS_VISIBLE) Window->head.pti->cVisWindows--;
+               if (Style.styleNew & WS_VISIBLE) Window->head.pti->cVisWindows++;
+               DceResetActiveDCEs( Window );
+            }
             Window->style = (DWORD)Style.styleNew;
             co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
             break;
@@ -3409,7 +3915,7 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
             break;
 
          default:
-            ERR("NtUserSetWindowLong(): Unsupported index %d\n", Index);
+            ERR("NtUserSetWindowLong(): Unsupported index %lu\n", Index);
             EngSetLastError(ERROR_INVALID_INDEX);
             OldValue = 0;
             break;
@@ -3438,6 +3944,12 @@ NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
    TRACE("Enter NtUserSetWindowLong\n");
    UserEnterExclusive();
 
+   if (hWnd == IntGetDesktopWindow())
+   {
+      EngSetLastError(STATUS_ACCESS_DENIED);
+      RETURN( 0);
+   }
+
    RETURN( co_UserSetWindowLong(hWnd, Index, NewValue, Ansi));
 
 CLEANUP:
@@ -3465,6 +3977,12 @@ NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue)
    TRACE("Enter NtUserSetWindowWord\n");
    UserEnterExclusive();
 
+   if (hWnd == IntGetDesktopWindow())
+   {
+      EngSetLastError(STATUS_ACCESS_DENIED);
+      RETURN( 0);
+   }
+
    if (!(Window = UserGetWindowObject(hWnd)))
    {
       RETURN( 0);
@@ -3475,7 +3993,7 @@ NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue)
       case GWL_ID:
       case GWL_HINSTANCE:
       case GWL_HWNDPARENT:
-         RETURN( (WORD)co_UserSetWindowLong(Window->head.h, Index, (UINT)NewValue, TRUE));
+         RETURN( (WORD)co_UserSetWindowLong(UserHMGetHandle(Window), Index, (UINT)NewValue, TRUE));
       default:
          if (Index < 0)
          {
@@ -3496,7 +4014,7 @@ NtUserSetWindowWord(HWND hWnd, INT Index, WORD NewValue)
    RETURN( OldValue);
 
 CLEANUP:
-   TRACE("Leave NtUserSetWindowWord, ret=%i\n",_ret_);
+   TRACE("Leave NtUserSetWindowWord, ret=%u\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -3521,6 +4039,10 @@ CLEANUP:
 DWORD APIENTRY
 NtUserQueryWindow(HWND hWnd, DWORD Index)
 {
+/* Console Leader Process CID Window offsets */
+#define GWLP_CONSOLE_LEADER_PID 0
+#define GWLP_CONSOLE_LEADER_TID 4
+
    PWND pWnd;
    DWORD Result;
    DECLARE_RETURN(UINT);
@@ -3536,12 +4058,34 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
    switch(Index)
    {
       case QUERY_WINDOW_UNIQUE_PROCESS_ID:
-         Result = (DWORD)IntGetWndProcessId(pWnd);
+      {
+         if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
+              (pWnd->pcls->atomClassName == gaGuiConsoleWndClass) )
+         {
+            // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_PID)
+            Result = (DWORD)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
+         }
+         else
+         {
+            Result = (DWORD)IntGetWndProcessId(pWnd);
+         }
          break;
+      }
 
       case QUERY_WINDOW_UNIQUE_THREAD_ID:
-         Result = (DWORD)IntGetWndThreadId(pWnd);
+      {
+         if ( (pWnd->head.pti->TIF_flags & TIF_CSRSSTHREAD) &&
+              (pWnd->pcls->atomClassName == gaGuiConsoleWndClass) )
+         {
+            // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_TID)
+            Result = (DWORD)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
+         }
+         else
+         {
+            Result = (DWORD)IntGetWndThreadId(pWnd);
+         }
          break;
+      }
 
       case QUERY_WINDOW_ACTIVE:
          Result = (DWORD)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
@@ -3552,7 +4096,7 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
          break;
 
       case QUERY_WINDOW_ISHUNG:
-         Result = (DWORD)MsqIsHung(pWnd->head.pti->MessageQueue);
+         Result = (DWORD)MsqIsHung(pWnd->head.pti);
          break;
 
       case QUERY_WINDOW_REAL_ID:
@@ -3571,7 +4115,7 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
    RETURN( Result);
 
 CLEANUP:
-   TRACE("Leave NtUserQueryWindow, ret=%i\n",_ret_);
+   TRACE("Leave NtUserQueryWindow, ret=%u\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -3610,7 +4154,7 @@ NtUserRegisterWindowMessage(PUNICODE_STRING MessageNameUnsafe)
    RETURN( Ret);
 
 CLEANUP:
-   TRACE("Leave NtUserRegisterWindowMessage, ret=%i\n",_ret_);
+   TRACE("Leave NtUserRegisterWindowMessage, ret=%u\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -3830,7 +4374,7 @@ NtUserDefSetText(HWND hWnd, PLARGE_STRING WindowText)
    /* Send shell notifications */
    if (!Wnd->spwndOwner && !IntGetParent(Wnd))
    {
-      co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd);
+      co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) hWnd, FALSE); // FIXME Flashing?
    }
 
    Ret = TRUE;
@@ -3907,7 +4451,9 @@ CLEANUP:
    END_CLEANUP;
 }
 
-
+/*
+  API Call
+*/
 BOOL
 FASTCALL
 IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
@@ -3918,7 +4464,8 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
 
 //   ASSERT(OwnerWnd);
 
-   win_array = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
+   TRACE("Enter ShowOwnedPopups Show: %s\n", (fShow ? "TRUE" : "FALSE"));
+   win_array = IntWinListChildren(OwnerWnd);
 
    if (!win_array)
       return TRUE;
@@ -3927,7 +4474,7 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
       count++;
    while (--count >= 0)
    {
-      if (!(pWnd = UserGetWindowObject( win_array[count] )))
+      if (!(pWnd = ValidateHwndNoErr( win_array[count] )))
          continue;
       if (pWnd->spwndOwner != OwnerWnd)
          continue;
@@ -3958,7 +4505,8 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
       }
 
    }
-   ExFreePool( win_array );
+   ExFreePoolWithTag(win_array, USERTAG_WINDOWLIST);
+   TRACE("Leave ShowOwnedPopups\n");
    return TRUE;
 }