[WIN32K:NTUSER] Optimize IntWinListOwnedPopups() a little bit. Improve a trace.
[reactos.git] / win32ss / user / ntuser / window.c
index 7dba263..4776b8e 100644 (file)
@@ -2,7 +2,7 @@
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS Win32k subsystem
  * PURPOSE:          Windows
- * FILE:             subsystems/win32/win32k/ntuser/window.c
+ * FILE:             win32ss/user/ntuser/window.c
  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
  */
 
@@ -65,9 +65,12 @@ PWND FASTCALL VerifyWnd(PWND pWnd)
 {
    HWND hWnd;
    UINT State, State2;
+   ULONG Error;
 
    if (!pWnd) return NULL;
 
+   Error = EngGetLastError();
+
    _SEH2_TRY
    {
       hWnd = UserHMGetHandle(pWnd);
@@ -76,6 +79,7 @@ PWND FASTCALL VerifyWnd(PWND pWnd)
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
+      EngSetLastError(Error);
       _SEH2_YIELD(return NULL);
    }
    _SEH2_END
@@ -83,8 +87,9 @@ PWND FASTCALL VerifyWnd(PWND pWnd)
    if ( UserObjectInDestroy(hWnd) ||
         State & WNDS_DESTROYED ||
         State2 & WNDS2_INDESTROY )
-      return NULL;
+      pWnd = NULL;
 
+   EngSetLastError(Error);
    return pWnd;
 }
 
@@ -125,7 +130,7 @@ IntSetStyle( PWND pwnd, ULONG set_bits, ULONG clear_bits )
     pwnd->style = styleNew;
     if ((styleOld ^ styleNew) & WS_VISIBLE) // State Change.
     {
-       if (styleOld & WS_VISIBLE) pwnd->head.pti->cVisWindows--; 
+       if (styleOld & WS_VISIBLE) pwnd->head.pti->cVisWindows--;
        if (styleNew & WS_VISIBLE) pwnd->head.pti->cVisWindows++;
        DceResetActiveDCEs( pwnd );
     }
@@ -249,29 +254,69 @@ IntEnableWindow( HWND hWnd, BOOL bEnable )
 HWND* FASTCALL
 IntWinListChildren(PWND Window)
 {
-   PWND Child;
-   HWND *List;
-   UINT Index, NumChildren = 0;
+    PWND Child;
+    HWND *List;
+    UINT Index, NumChildren = 0;
 
-   if (!Window) return NULL;
+    if (!Window) return NULL;
 
-   for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
-      ++NumChildren;
+    for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
+    {
+        ++NumChildren;
+    }
 
-   List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
-   if(!List)
-   {
-      ERR("Failed to allocate memory for children array\n");
-      EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return NULL;
-   }
-   for (Child = Window->spwndChild, Index = 0;
-         Child != NULL;
-         Child = Child->spwndNext, ++Index)
-      List[Index] = Child->head.h;
-   List[Index] = NULL;
+    List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
+    if(!List)
+    {
+        ERR("Failed to allocate memory for children array\n");
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+
+    Index = 0;
+    for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
+    {
+        List[Index++] = Child->head.h;
+    }
+    List[Index] = NULL;
+
+    return List;
+}
 
-   return List;
+HWND* FASTCALL
+IntWinListOwnedPopups(PWND Window)
+{
+    PWND Child, Desktop;
+    HWND *List;
+    UINT Index, NumOwned = 0;
+
+    Desktop = co_GetDesktopWindow(Window);
+    if (!Desktop)
+        return NULL;
+
+    for (Child = Desktop->spwndChild; Child; Child = Child->spwndNext)
+    {
+        if (Child->spwndOwner == Window)
+            ++NumOwned;
+    }
+
+    List = ExAllocatePoolWithTag(PagedPool, (NumOwned + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
+    if (!List)
+    {
+        ERR("Failed to allocate memory for children array\n");
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+
+    Index = 0;
+    for (Child = Desktop->spwndChild; Child; Child = Child->spwndNext)
+    {
+        if (Child->spwndOwner == Window)
+            List[Index++] = Child->head.h;
+    }
+    List[Index] = NULL;
+
+    return List;
 }
 
 PWND FASTCALL
@@ -340,7 +385,7 @@ IntGetWindow(HWND hWnd,
                 if (Wnd->spwndPrev != NULL)
                     FoundWnd = Wnd->spwndPrev;
                 break;
-   
+
             case GW_CHILD:
                 if (Wnd->spwndChild != NULL)
                     FoundWnd = Wnd->spwndChild;
@@ -362,78 +407,106 @@ IntGetWindow(HWND hWnd,
     return Ret;
 }
 
+DWORD FASTCALL IntGetWindowContextHelpId( PWND pWnd )
+{
+   DWORD HelpId;
+
+   do
+   {
+      HelpId = (DWORD)(DWORD_PTR)UserGetProp(pWnd, gpsi->atomContextHelpIdProp, TRUE);
+      if (!HelpId) break;
+      pWnd = IntGetParent(pWnd);
+   }
+   while (pWnd && pWnd->fnid != FNID_DESKTOP);
+   return HelpId;
+}
+
+
+VOID
+FASTCALL
+IntRemoveTrackMouseEvent(
+    PDESKTOP pDesk);
+
 /***********************************************************************
  *           IntSendDestroyMsg
  */
 static void IntSendDestroyMsg(HWND hWnd)
 {
-
+   PTHREADINFO ti;
    PWND Window;
-#if 0 /* FIXME */
 
-   GUITHREADINFO info;
+   ti = PsGetCurrentThreadWin32Thread();
+   Window = UserGetWindowObject(hWnd);
 
-   if (GetGUIThreadInfo(GetCurrentThreadId(), &info))
+   if (Window)
    {
-      if (hWnd == info.hwndCaret)
+      /*
+       * Look whether the focus is within the tree of windows
+       * we will be destroying.
+       */
+      // Rule #1
+      if ( ti->MessageQueue->spwndActive == Window || // Fixes CORE-106 RegSvr32 exit and return focus to CMD.
+          (ti->MessageQueue->spwndActive == NULL && ti->MessageQueue == IntGetFocusMessageQueue()) )
       {
-         DestroyCaret();
+         co_WinPosActivateOtherWindow(Window);
       }
-   }
-#endif
 
-   Window = UserGetWindowObject(hWnd);
-   if (Window)
-   {
-//      USER_REFERENCE_ENTRY Ref;
-//      UserRefObjectCo(Window, &Ref);
+      /* Fixes CMD properties closing and returning focus to CMD */
+      if (ti->MessageQueue->spwndFocus == Window)
+      {
+         if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+         {
+            co_UserSetFocus(Window->spwndParent);
+         }
+         else
+         {
+            co_UserSetFocus(NULL);
+         }
+      }
 
-      if (!Window->spwndOwner && !IntGetParent(Window))
+      if (ti->MessageQueue->CaretInfo.hWnd == UserHMGetHandle(Window))
       {
-         co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM) hWnd, 0);
+         co_IntDestroyCaret(ti);
       }
 
-//      UserDerefObjectCo(Window);
+      /* If the window being destroyed is currently tracked... */
+      if (ti->rpdesk->spwndTrack == Window)
+      {
+          IntRemoveTrackMouseEvent(ti->rpdesk);
+      }
    }
 
-   /* The window could already be destroyed here */
-
-   /*
-    * Send the WM_DESTROY to the window.
-    */
+   /* If the window being destroyed is the current clipboard owner... */
+   if (ti->ppi->prpwinsta != NULL && Window == ti->ppi->prpwinsta->spwndClipOwner)
+   {
+       /* ... make it release the clipboard */
+       UserClipboardRelease(Window);
+   }
 
+   /* Send the WM_DESTROY to the window */
    co_IntSendMessage(hWnd, WM_DESTROY, 0, 0);
 
    /*
     * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
     * make sure that the window still exists when we come back.
     */
-#if 0 /* FIXME */
-
-   if (IsWindow(Wnd))
+   if (IntIsWindow(hWnd))
    {
       HWND* pWndArray;
       int i;
 
-      if (!(pWndArray = WIN_ListChildren( hwnd )))
-         return;
+      if (!(pWndArray = IntWinListChildren( Window ))) return;
 
-      /* start from the end (FIXME: is this needed?) */
       for (i = 0; pWndArray[i]; i++)
-         ;
-
-      while (--i >= 0)
       {
-         if (IsWindow( pWndArray[i] ))
-            WIN_SendDestroyMsg( pWndArray[i] );
+         if (IntIsWindow( pWndArray[i] )) IntSendDestroyMsg( pWndArray[i] );
       }
-      HeapFree(GetProcessHeap(), 0, pWndArray);
+      ExFreePoolWithTag(pWndArray, USERTAG_WINDOWLIST);
    }
    else
    {
       TRACE("destroyed itself while in WM_DESTROY!\n");
    }
-#endif
 }
 
 static VOID
@@ -463,18 +536,17 @@ UserFreeWindowInfo(PTHREADINFO ti, PWND Wnd)
 }
 
 /***********************************************************************
- *           IntDestroyWindow
+ *           co_UserFreeWindow
  *
  * Destroy storage associated to a window. "Internals" p.358
  *
- * This is the "functional" DestroyWindows function ei. all stuff
- * done in CreateWindow is undone here and not in DestroyWindow:-P
-
+ * This is the "functional" DestroyWindows function i.e. all stuff
+ * done in CreateWindow is undone here and not in DestroyWindow :-P
  */
-static LRESULT co_UserFreeWindow(PWND Window,
-                                   PPROCESSINFO ProcessData,
-                                   PTHREADINFO ThreadData,
-                                   BOOLEAN SendMessages)
+LRESULT co_UserFreeWindow(PWND Window,
+                          PPROCESSINFO ProcessData,
+                          PTHREADINFO ThreadData,
+                          BOOLEAN SendMessages)
 {
    HWND *Children;
    HWND *ChildHandle;
@@ -486,29 +558,22 @@ static LRESULT co_UserFreeWindow(PWND Window,
 
    if(Window->state2 & WNDS2_INDESTROY)
    {
-      TRACE("Tried to call IntDestroyWindow() twice\n");
+      TRACE("Tried to call co_UserFreeWindow() twice\n");
       return 0;
    }
    Window->state2 |= WNDS2_INDESTROY;
    Window->style &= ~WS_VISIBLE;
    Window->head.pti->cVisWindows--;
 
-   IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
 
    /* remove the window already at this point from the thread window list so we
       don't get into trouble when destroying the thread windows while we're still
-      in IntDestroyWindow() */
+      in co_UserFreeWindow() */
    RemoveEntryList(&Window->ThreadListEntry);
 
    BelongsToThreadData = IntWndBelongsToThread(Window, ThreadData);
 
-   IntDeRegisterShellHookWindow(Window->head.h);
-
-   if(SendMessages)
-   {
-      /* Send destroy messages */
-      IntSendDestroyMsg(Window->head.h);
-   }
+   IntDeRegisterShellHookWindow(UserHMGetHandle(Window));
 
    /* free child windows */
    Children = IntWinListChildren(Window);
@@ -518,10 +583,10 @@ static LRESULT co_UserFreeWindow(PWND Window,
       {
          if ((Child = IntGetWindowObject(*ChildHandle)))
          {
-            if(!IntWndBelongsToThread(Child, ThreadData))
+            if (!IntWndBelongsToThread(Child, ThreadData))
             {
                /* send WM_DESTROY messages to windows not belonging to the same thread */
-               IntSendDestroyMsg(Child->head.h);
+               co_IntSendMessage( UserHMGetHandle(Child), WM_ASYNC_DESTROYWINDOW, 0, 0 );
             }
             else
                co_UserFreeWindow(Child, ProcessData, ThreadData, SendMessages);
@@ -532,7 +597,7 @@ static LRESULT co_UserFreeWindow(PWND Window,
       ExFreePoolWithTag(Children, USERTAG_WINDOWLIST);
    }
 
-   if(SendMessages)
+   if (SendMessages)
    {
       /*
        * Clear the update region to make sure no WM_PAINT messages will be
@@ -541,14 +606,16 @@ static LRESULT co_UserFreeWindow(PWND Window,
       co_UserRedrawWindow(Window, NULL, 0,
                           RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
                           RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
-      if(BelongsToThreadData)
-         co_IntSendMessage(Window->head.h, WM_NCDESTROY, 0, 0);
+      if (BelongsToThreadData)
+         co_IntSendMessage(UserHMGetHandle(Window), WM_NCDESTROY, 0, 0);
    }
 
+   UserClipboardFreeWindow(Window);
+
    DestroyTimersForWindow(ThreadData, Window);
 
    /* Unregister hot keys */
-   UnregisterWindowHotKeys (Window);
+   UnregisterWindowHotKeys(Window);
 
    /* flush the message queue */
    MsqRemoveWindowMessagesFromQueue(Window);
@@ -560,7 +627,7 @@ static LRESULT co_UserFreeWindow(PWND Window,
    /* don't remove the WINDOWSTATUS_DESTROYING bit */
 
    /* reset shell window handles */
-   if(ThreadData->rpdesk)
+   if (ThreadData->rpdesk)
    {
       if (Window->head.h == ThreadData->rpdesk->rpwinstaParent->ShellWindow)
          ThreadData->rpdesk->rpwinstaParent->ShellWindow = NULL;
@@ -569,63 +636,82 @@ static LRESULT co_UserFreeWindow(PWND Window,
          ThreadData->rpdesk->rpwinstaParent->ShellListView = NULL;
    }
 
-   /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
+   /* Fixes dialog test_focus breakage due to r66237. */
+   if (ThreadData->MessageQueue->spwndFocus == Window)
+      ThreadData->MessageQueue->spwndFocus = NULL;
 
-#if 0 /* FIXME */
+   if (ThreadData->MessageQueue->spwndActive == Window)
+      ThreadData->MessageQueue->spwndActive = NULL;
 
-   WinPosCheckInternalPos(Window->head.h);
-   if (Window->head.h == GetCapture())
+   if (ThreadData->MessageQueue->spwndCapture == Window)
    {
-      ReleaseCapture();
+      IntReleaseCapture();
    }
 
-   /* free resources associated with the window */
-   TIMER_RemoveWindowTimers(Window->head.h);
-#endif
+   //// Now kill those remaining "PAINTING BUG: Thread marked as containing dirty windows" spam!!!
+   if ( Window->hrgnUpdate != NULL || Window->state & WNDS_INTERNALPAINT )
+   {
+      MsqDecPaintCountQueue(Window->head.pti);
+      if (Window->hrgnUpdate > HRGN_WINDOW && GreIsHandleValid(Window->hrgnUpdate))
+      {
+         IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+         GreDeleteObject(Window->hrgnUpdate);
+      }
+      Window->hrgnUpdate = NULL;
+      Window->state &= ~WNDS_INTERNALPAINT;
+   }
+
+   if (Window->state & (WNDS_SENDERASEBACKGROUND|WNDS_SENDNCPAINT))
+   {
+      Window->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_SENDNCPAINT);
+   }
 
    if ( ((Window->style & (WS_CHILD|WS_POPUP)) != WS_CHILD) &&
         Window->IDMenu &&
         (Menu = UserGetMenuObject((HMENU)Window->IDMenu)))
    {
-      IntDestroyMenuObject(Menu, TRUE, TRUE);
+      TRACE("UFW: IDMenu %p\n",Window->IDMenu);
+      IntDestroyMenuObject(Menu, TRUE);
       Window->IDMenu = 0;
    }
 
-   if(Window->SystemMenu
-         && (Menu = UserGetMenuObject(Window->SystemMenu)))
+   if (Window->SystemMenu
+        && (Menu = UserGetMenuObject(Window->SystemMenu)))
    {
-      IntDestroyMenuObject(Menu, TRUE, TRUE);
+      IntDestroyMenuObject(Menu, TRUE);
       Window->SystemMenu = (HMENU)0;
    }
 
    DceFreeWindowDCE(Window);    /* Always do this to catch orphaned DCs */
-#if 0 /* FIXME */
-
-   WINPROC_FreeProc(Window->winproc, WIN_PROC_WINDOW);
-   CLASS_RemoveWindow(Window->Class);
-#endif
 
    IntUnlinkWindow(Window);
 
    if (Window->PropListItems)
    {
-      IntRemoveWindowProp(Window);
-      TRACE("Window->PropListItems %d\n",Window->PropListItems);
+      UserRemoveWindowProps(Window);
+      TRACE("Window->PropListItems %lu\n",Window->PropListItems);
       ASSERT(Window->PropListItems==0);
    }
 
    UserReferenceObject(Window);
-   UserDeleteObject(Window->head.h, TYPE_WINDOW);
+   UserMarkObjectDestroy(Window);
 
    IntDestroyScrollBars(Window);
 
+   if (Window->pcls->atomClassName == gaGuiConsoleWndClass)
+   {
+       /* Count only console windows manually */
+       co_IntUserManualGuiCheck(FALSE);
+   }
+
    /* dereference the class */
+   NT_ASSERT(Window->head.pti != NULL);
    IntDereferenceClass(Window->pcls,
                        Window->head.pti->pDeskInfo,
                        Window->head.pti->ppi);
    Window->pcls = NULL;
 
-   if(Window->hrgnClip)
+   if (Window->hrgnClip)
    {
       IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED);
       GreDeleteObject(Window->hrgnClip);
@@ -637,8 +723,7 @@ static LRESULT co_UserFreeWindow(PWND Window,
    UserFreeWindowInfo(Window->head.pti, Window);
 
    UserDereferenceObject(Window);
-
-   UserClipboardFreeWindow(Window);
+   UserDeleteObject(UserHMGetHandle(Window), TYPE_WINDOW);
 
    return 0;
 }
@@ -786,278 +871,64 @@ IntSetWindowProc(PWND pWnd,
    return Ret;
 }
 
-static BOOL FASTCALL
-IntSetMenu(
-   PWND Wnd,
-   HMENU Menu,
-   BOOL *Changed)
-{
-   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;
-   }
-
-   *Changed = (Wnd->IDMenu != (UINT) Menu);
-   if (! *Changed)
-   {
-      return TRUE;
-   }
-
-   if (Wnd->IDMenu)
-   {
-      OldMenu = IntGetMenuObject((HMENU) Wnd->IDMenu);
-      ASSERT(NULL == OldMenu || OldMenu->hWnd == Wnd->head.h);
-   }
-   else
-   {
-      OldMenu = NULL;
-   }
-
-   if (NULL != Menu)
-   {
-      NewMenu = IntGetMenuObject(Menu);
-      if (NULL == NewMenu)
-      {
-         if (NULL != OldMenu)
-         {
-            IntReleaseMenuObject(OldMenu);
-         }
-         EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-         return FALSE;
-      }
-      if (NULL != NewMenu->hWnd)
-      {
-         /* Can't use the same menu for two windows */
-         if (NULL != OldMenu)
-         {
-            IntReleaseMenuObject(OldMenu);
-         }
-         EngSetLastError(ERROR_INVALID_MENU_HANDLE);
-         return FALSE;
-      }
-
-   }
-
-   Wnd->IDMenu = (UINT) Menu;
-   if (NULL != NewMenu)
-   {
-      NewMenu->hWnd = Wnd->head.h;
-      IntReleaseMenuObject(NewMenu);
-   }
-   if (NULL != OldMenu)
-   {
-      OldMenu->hWnd = NULL;
-      IntReleaseMenuObject(OldMenu);
-   }
-
-   return TRUE;
-}
-
 
 /* INTERNAL ******************************************************************/
 
-
-VOID FASTCALL
-co_DestroyThreadWindows(struct _ETHREAD *Thread)
-{
-   PTHREADINFO WThread;
-   PLIST_ENTRY Current;
-   PWND Wnd;
-   USER_REFERENCE_ENTRY Ref;
-   WThread = (PTHREADINFO)Thread->Tcb.Win32Thread;
-
-   while (!IsListEmpty(&WThread->WindowListHead))
-   {
-      Current = WThread->WindowListHead.Flink;
-      Wnd = CONTAINING_RECORD(Current, WND, ThreadListEntry);
-
-      TRACE("thread cleanup: while destroy wnds, wnd=%p\n", Wnd);
-
-      /* Window removes itself from the list */
-
-      /*
-       * FIXME: It is critical that the window removes itself! If now, we will loop
-       * here forever...
-       */
-
-      //ASSERT(co_UserDestroyWindow(Wnd));
-
-      UserRefObjectCo(Wnd, &Ref); // FIXME: Temp HACK??
-      if (!co_UserDestroyWindow(Wnd))
-      {
-         ERR("Unable to destroy window %p at thread cleanup... This is _VERY_ bad!\n", Wnd);
-      }
-      UserDerefObjectCo(Wnd); // FIXME: Temp HACK??
-   }
-}
-
-PMENU FASTCALL
-IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu)
-{
-   PMENU Menu, NewMenu = NULL, SysMenu = NULL, ret = NULL;
-   PTHREADINFO W32Thread;
-   HMENU hNewMenu, hSysMenu;
-   ROSMENUITEMINFO ItemInfo = {0};
-
-   if(bRevert)
-   {
-      W32Thread = PsGetCurrentThreadWin32Thread();
-
-      if(!W32Thread->rpdesk)
-         return NULL;
-
-      if(Window->SystemMenu)
-      {
-         Menu = UserGetMenuObject(Window->SystemMenu);
-         if(Menu)
-         {
-            IntDestroyMenuObject(Menu, TRUE, TRUE);
-            Window->SystemMenu = (HMENU)0;
-         }
-      }
-
-      if(W32Thread->rpdesk->rpwinstaParent->SystemMenuTemplate)
-      {
-         /* Clone system menu */
-         Menu = UserGetMenuObject(W32Thread->rpdesk->rpwinstaParent->SystemMenuTemplate);
-         if(!Menu)
-            return NULL;
-
-         NewMenu = IntCloneMenu(Menu);
-         if(NewMenu)
-         {  // Use spmenuSys
-            Window->SystemMenu = NewMenu->head.h;
-            NewMenu->fFlags |= MNF_SYSDESKMN;
-            NewMenu->hWnd = Window->head.h;
-            ret = NewMenu;
-            //IntReleaseMenuObject(NewMenu);
-         }
-      }
-      else
-      {
-         hSysMenu = UserCreateMenu(FALSE);
-         if (NULL == hSysMenu)
-         {
-            return NULL;
-         }
-         SysMenu = IntGetMenuObject(hSysMenu);
-         if (NULL == SysMenu)
-         {
-            UserDestroyMenu(hSysMenu);
-            return NULL;
-         }
-         SysMenu->fFlags |= MNF_SYSDESKMN;
-         SysMenu->hWnd = Window->head.h;
-         hNewMenu = co_IntLoadSysMenuTemplate();
-         //if ( Window->ExStyle & WS_EX_MDICHILD )
-         //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENUMDI");
-         // else
-         //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENU");
-         // Do the rest in here.
-         if(!hNewMenu)
-         {
-            IntReleaseMenuObject(SysMenu);
-            UserDestroyMenu(hSysMenu);
-            return NULL;
-         }
-         Menu = IntGetMenuObject(hNewMenu);
-         if(!Menu)
-         {
-            IntReleaseMenuObject(SysMenu);
-            UserDestroyMenu(hSysMenu);
-            return NULL;
-         }
-
-         NewMenu = IntCloneMenu(Menu);
-         if(NewMenu)
-         {
-            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 = 0;
-            ItemInfo.fState = MFS_ENABLED;
-            ItemInfo.dwTypeData = NULL;
-            ItemInfo.cch = 0;
-            ItemInfo.hSubMenu = NewMenu->head.h;
-            IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo, NULL);
-
-            Window->SystemMenu = SysMenu->head.h;
-
-            ret = SysMenu;
-         }
-         IntDestroyMenuObject(Menu, FALSE, TRUE);
-      }
-      if(RetMenu)
-         return ret;
-      else
-         return NULL;
-   }
-   else
-   {
-      if(Window->SystemMenu)
-         return IntGetMenuObject((HMENU)Window->SystemMenu);
-      else
-         return NULL;
-   }
-}
-
-
+////
+//   This fixes a check for children messages that need paint while searching the parents messages!
+//   Fixes wine msg:test_paint_messages:WmParentErasePaint ..
+////
 BOOL FASTCALL
 IntIsChildWindow(PWND Parent, PWND BaseWindow)
 {
-   PWND Window;
-
-   Window = BaseWindow;
-   while (Window && ((Window->style & (WS_POPUP|WS_CHILD)) == WS_CHILD))
+   PWND Window = BaseWindow;
+   do
    {
-      if (Window == Parent)
-      {
-         return(TRUE);
-      }
+     if ( Window == NULL || (Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD )
+        return FALSE;
 
-      Window = Window->spwndParent;
+     Window = Window->spwndParent;
    }
-
-   return(FALSE);
+   while(Parent != Window);
+   return TRUE;
 }
+////
 
-/*
-   Link the window into siblings list
-   children and parent are kept in place.
-*/
+/* Link the window into siblings list. Children and parent are kept in place. */
 VOID FASTCALL
 IntLinkWindow(
-   PWND Wnd,
-   PWND WndInsertAfter /* set to NULL if top sibling */
+    PWND Wnd,
+    PWND WndInsertAfter /* Set to NULL if top sibling */
 )
 {
-  if ((Wnd->spwndPrev = WndInsertAfter))
-   {
-      /* link after WndInsertAfter */
-      if ((Wnd->spwndNext = WndInsertAfter->spwndNext))
-         Wnd->spwndNext->spwndPrev = Wnd;
+    if (Wnd == WndInsertAfter)
+    {
+        ERR("IntLinkWindow -- Trying to link window 0x%p to itself!!\n", Wnd);
+        return;
+    }
 
-      Wnd->spwndPrev->spwndNext = Wnd;
-   }
-   else
-   {
-      /* link at top */
-     if ((Wnd->spwndNext = Wnd->spwndParent->spwndChild))
-         Wnd->spwndNext->spwndPrev = Wnd;
+    Wnd->spwndPrev = WndInsertAfter;
+    if (Wnd->spwndPrev)
+    {
+        /* Link after WndInsertAfter */
+        ASSERT(Wnd != WndInsertAfter->spwndNext);
+        Wnd->spwndNext = WndInsertAfter->spwndNext;
+        if (Wnd->spwndNext)
+            Wnd->spwndNext->spwndPrev = Wnd;
+
+        ASSERT(Wnd != Wnd->spwndPrev);
+        Wnd->spwndPrev->spwndNext = Wnd;
+    }
+    else
+    {
+        /* Link at the top */
+        ASSERT(Wnd != Wnd->spwndParent->spwndChild);
+        Wnd->spwndNext = Wnd->spwndParent->spwndChild;
+        if (Wnd->spwndNext)
+            Wnd->spwndNext->spwndPrev = Wnd;
 
-     Wnd->spwndParent->spwndChild = Wnd;
-   }
+        Wnd->spwndParent->spwndChild = Wnd;
+    }
 }
 
 /*
@@ -1067,8 +938,8 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
 {
     if (hWndPrev == HWND_NOTOPMOST)
     {
-        if (!(Wnd->ExStyle & WS_EX_TOPMOST) &&
-            (Wnd->ExStyle2 & WS_EX2_LINKED)) return;  /* nothing to do */
+        if (!(Wnd->ExStyle & WS_EX_TOPMOST) && (Wnd->ExStyle2 & WS_EX2_LINKED))
+            return;  /* nothing to do */
         Wnd->ExStyle &= ~WS_EX_TOPMOST;
         hWndPrev = HWND_TOP;  /* fallback to the HWND_TOP case */
     }
@@ -1081,8 +952,10 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
         PWND WndInsertAfter;
 
         WndInsertAfter = Wnd->spwndParent->spwndChild;
-        while( WndInsertAfter && WndInsertAfter->spwndNext)
+        while (WndInsertAfter && WndInsertAfter->spwndNext)
+        {
             WndInsertAfter = WndInsertAfter->spwndNext;
+        }
 
         IntLinkWindow(Wnd, WndInsertAfter);
         Wnd->ExStyle &= ~WS_EX_TOPMOST;
@@ -1091,7 +964,6 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
     {
         /* Link in the top of the list */
         IntLinkWindow(Wnd, NULL);
-
         Wnd->ExStyle |= WS_EX_TOPMOST;
     }
     else if (hWndPrev == HWND_TOP)
@@ -1105,7 +977,9 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
         {
             while (WndInsertBefore != NULL && WndInsertBefore->spwndNext != NULL)
             {
-                if (!(WndInsertBefore->ExStyle & WS_EX_TOPMOST)) break;
+                if (!(WndInsertBefore->ExStyle & WS_EX_TOPMOST))
+                    break;
+
                 if (WndInsertBefore == Wnd->spwndOwner)  /* keep it above owner */
                 {
                     Wnd->ExStyle |= WS_EX_TOPMOST;
@@ -1124,13 +998,15 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
 
         WndInsertAfter = UserGetWindowObject(hWndPrev);
         /* Are we called with an erroneous handle */
-        if(WndInsertAfter == NULL)
+        if (WndInsertAfter == NULL)
         {
             /* Link in a default position */
             IntLinkHwnd(Wnd, HWND_TOP);
             return;
         }
 
+        if (Wnd == WndInsertAfter)
+            ERR("IntLinkHwnd -- Trying to link window 0x%p to itself!!\n", Wnd);
         IntLinkWindow(Wnd, WndInsertAfter);
 
         /* Fix the WS_EX_TOPMOST flag */
@@ -1140,8 +1016,8 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev)
         }
         else
         {
-            if(WndInsertAfter->spwndNext &&
-               WndInsertAfter->spwndNext->ExStyle & WS_EX_TOPMOST)
+            if (WndInsertAfter->spwndNext &&
+                (WndInsertAfter->spwndNext->ExStyle & WS_EX_TOPMOST))
             {
                 Wnd->ExStyle |= WS_EX_TOPMOST;
             }
@@ -1315,8 +1191,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
       /* Link the window with its new siblings */
       IntLinkHwnd( Wnd,
                   ((0 == (Wnd->ExStyle & WS_EX_TOPMOST) &&
-                    WndNewParent == UserGetDesktopWindow() ) ? HWND_TOP : HWND_TOPMOST ) );
-
+                    UserIsDesktopWindow(WndNewParent) ) ? HWND_TOP : HWND_TOPMOST ) );
    }
 
    if ( WndNewParent == co_GetDesktopWindow(Wnd) &&
@@ -1332,7 +1207,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
    {
       if ( Wnd->spwndParent != co_GetDesktopWindow(Wnd))
       {
-         if (Wnd->head.pti != WndOldParent->head.pti)
+         if (WndOldParent && (Wnd->head.pti != WndOldParent->head.pti))
          {
             //ERR("SetParent Old out.\n");
             UserAttachThreadInput(Wnd->head.pti, WndOldParent->head.pti, FALSE);
@@ -1348,7 +1223,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
       }
    }
 
-   if (WndOldParent == UserGetMessageWindow() || WndNewParent == UserGetMessageWindow())
+   if (UserIsMessageWindow(WndOldParent) || UserIsMessageWindow(WndNewParent))
       swFlags |= SWP_NOACTIVATE;
 
    IntNotifyWinEvent(EVENT_OBJECT_PARENTCHANGE, Wnd ,OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
@@ -1426,46 +1301,23 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent)
    return( hWndOldParent);
 }
 
-BOOL FASTCALL
-IntSetSystemMenu(PWND Window, PMENU Menu)
-{
-   PMENU OldMenu;
-   if(Window->SystemMenu)
-   {
-      OldMenu = IntGetMenuObject(Window->SystemMenu);
-      if(OldMenu)
-      {
-         OldMenu->fFlags &= ~ MNF_SYSDESKMN;
-         IntReleaseMenuObject(OldMenu);
-      }
-   }
-
-   if(Menu)
-   {
-      /* FIXME: Check window style, propably return FALSE? */
-      Window->SystemMenu = Menu->head.h;
-      Menu->fFlags |= MNF_SYSDESKMN;
-   }
-   else // Use spmenuSys too!
-      Window->SystemMenu = (HMENU)0;
-
-   return TRUE;
-}
-
-/* Unlink the window from siblings. children and parent are kept in place. */
+/* Unlink the window from siblings. Children and parent are kept in place. */
 VOID FASTCALL
 IntUnlinkWindow(PWND Wnd)
 {
-   if (Wnd->spwndNext)
-       Wnd->spwndNext->spwndPrev = Wnd->spwndPrev;
+    ASSERT(Wnd != Wnd->spwndNext);
+    ASSERT(Wnd != Wnd->spwndPrev);
+
+    if (Wnd->spwndNext)
+        Wnd->spwndNext->spwndPrev = Wnd->spwndPrev;
 
-   if (Wnd->spwndPrev)
-       Wnd->spwndPrev->spwndNext = Wnd->spwndNext;
+    if (Wnd->spwndPrev)
+        Wnd->spwndPrev->spwndNext = Wnd->spwndNext;
 
-   if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd)
-       Wnd->spwndParent->spwndChild = Wnd->spwndNext;
+    if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd)
+        Wnd->spwndParent->spwndChild = Wnd->spwndNext;
 
-   Wnd->spwndPrev = Wnd->spwndNext = NULL;
+    Wnd->spwndPrev = Wnd->spwndNext = NULL;
 }
 
 /* FUNCTIONS *****************************************************************/
@@ -1587,10 +1439,10 @@ NtUserBuildHwndList(
    {
       PETHREAD Thread;
       PTHREADINFO W32Thread;
-      PLIST_ENTRY Current;
       PWND Window;
+      HWND *List = NULL;
 
-      Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
+      Status = PsLookupThreadByThreadId(UlongToHandle(dwThreadId), &Thread);
       if (!NT_SUCCESS(Status))
       {
          ERR("Thread Id is not valid!\n");
@@ -1599,53 +1451,61 @@ NtUserBuildHwndList(
       if (!(W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread))
       {
          ObDereferenceObject(Thread);
-         ERR("Thread is not initialized!\n");
+         TRACE("Tried to enumerate windows of a non gui thread\n");
          return ERROR_INVALID_PARAMETER;
       }
 
-      Current = W32Thread->WindowListHead.Flink;
-      while (Current != &(W32Thread->WindowListHead))
+     // Do not use Thread link list due to co_UserFreeWindow!!!
+     // Current = W32Thread->WindowListHead.Flink;
+     // Fixes Api:CreateWindowEx tests!!!
+      List = IntWinListChildren(UserGetDesktopWindow());
+      if (List)
       {
-         Window = CONTAINING_RECORD(Current, WND, ThreadListEntry);
-         ASSERT(Window);
-
-         if (dwCount < *pBufSize && pWnd)
+         int i;
+         for (i = 0; List[i]; i++)
          {
-            _SEH2_TRY
-            {
-               ProbeForWrite(pWnd, sizeof(HWND), 1);
-               *pWnd = Window->head.h;
-               pWnd++;
-            }
-            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-            {
-               Status = _SEH2_GetExceptionCode();
-            }
-            _SEH2_END
-            if (!NT_SUCCESS(Status))
+            Window = ValidateHwndNoErr(List[i]);
+            if (Window && Window->head.pti == W32Thread)
             {
-               ERR("Failure to build window list!\n");
-               SetLastNtError(Status);
-               break;
-            }
-         }
-         dwCount++;
-         Current = Window->ThreadListEntry.Flink;
-      }
-
-      ObDereferenceObject(Thread);
-   }
-
-   *pBufSize = dwCount;
+               if (dwCount < *pBufSize && pWnd)
+               {
+                  _SEH2_TRY
+                  {
+                     ProbeForWrite(pWnd, sizeof(HWND), 1);
+                     *pWnd = Window->head.h;
+                     pWnd++;
+                  }
+                  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                  {
+                     Status = _SEH2_GetExceptionCode();
+                  }
+                  _SEH2_END
+                  if (!NT_SUCCESS(Status))
+                  {
+                     ERR("Failure to build window list!\n");
+                     SetLastNtError(Status);
+                     break;
+                  }
+               }
+               dwCount++;
+            }
+         }
+         ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
+      }
+
+      ObDereferenceObject(Thread);
+   }
+
+   *pBufSize = dwCount;
    return STATUS_SUCCESS;
 }
 
 static void IntSendParentNotify( PWND pWindow, UINT msg )
 {
     if ( (pWindow->style & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
-         !(pWindow->style & WS_EX_NOPARENTNOTIFY))
+         !(pWindow->ExStyle & WS_EX_NOPARENTNOTIFY))
     {
-        if (pWindow->spwndParent && pWindow->spwndParent != UserGetDesktopWindow())
+        if (VerifyWnd(pWindow->spwndParent) && !UserIsDesktopWindow(pWindow->spwndParent))
         {
             USER_REFERENCE_ENTRY Ref;
             UserRefObjectCo(pWindow->spwndParent, &Ref);
@@ -1760,7 +1620,6 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    PWND pWnd = NULL;
    HWND hWnd;
    PTHREADINFO pti = NULL;
-   PMENU SystemMenu;
    BOOL MenuChanged;
    BOOL bUnicodeWindow;
 
@@ -1854,13 +1713,35 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
 
    pWnd->head.pti->cWindows++;
 
-   if (Class->hIcon && !Class->hIconSm)
+   if (Class->spicn && !Class->spicnSm)
    {
-      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;
+       HICON IconSmHandle = NULL;
+       if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
+               == (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
+       {
+           IconSmHandle = co_IntCopyImage(
+               UserHMGetHandle(Class->spicn),
+               IMAGE_ICON,
+               UserGetSystemMetrics( SM_CXSMICON ),
+               UserGetSystemMetrics( SM_CYSMICON ),
+               LR_COPYFROMRESOURCE);
+       }
+       if (!IconSmHandle)
+       {
+           /* Retry without copying from resource */
+           IconSmHandle = co_IntCopyImage(
+               UserHMGetHandle(Class->spicn),
+               IMAGE_ICON,
+               UserGetSystemMetrics( SM_CXSMICON ),
+               UserGetSystemMetrics( SM_CYSMICON ),
+               0);
+       }
+
+       if (IconSmHandle)
+       {
+           Class->spicnSm = UserGetCurIconObject(IconSmHandle);
+           Class->CSF_flags |= CSF_CACHEDSMICON;
+       }
    }
 
    if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC)
@@ -1933,7 +1814,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    if (Class->atomClassName == gpsi->atomSysClass[ICLS_EDIT])
    {
       PCALLPROCDATA CallProc;
-      CallProc = CreateCallProc(NULL, pWnd->lpfnWndProc, pWnd->Unicode , pWnd->head.pti->ppi);
+      CallProc = CreateCallProc(pWnd->head.rpdesk, pWnd->lpfnWndProc, pWnd->Unicode , pWnd->head.pti->ppi);
 
       if (!CallProc)
       {
@@ -1947,6 +1828,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    }
 
    InitializeListHead(&pWnd->PropListHead);
+   pWnd->PropListItems = 0;
 
    if ( WindowName->Buffer != NULL && WindowName->Length > 0 )
    {
@@ -1988,22 +1870,13 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    if (!(pWnd->style & (WS_CHILD | WS_POPUP)))
       pWnd->state |= WNDS_SENDSIZEMOVEMSGS;
 
-   /* Create system menu */
-   if ((Cs->style & WS_SYSMENU)) // && (dwStyle & WS_CAPTION) == WS_CAPTION)
-   {
-      SystemMenu = IntGetSystemMenu(pWnd, TRUE, TRUE);
-      if(SystemMenu)
-      {  //    spmenuSys
-         pWnd->SystemMenu = SystemMenu->head.h;
-         IntReleaseMenuObject(SystemMenu);
-      }
-   }
-
    /* Set the window menu */
    if ((Cs->style & (WS_CHILD | WS_POPUP)) != WS_CHILD)
    {
-       if (Cs->hMenu)
+      if (Cs->hMenu)
+      {
          IntSetMenu(pWnd, Cs->hMenu, &MenuChanged);
+      }
       else if (pWnd->pcls->lpszMenuName) // Take it from the parent.
       {
           UNICODE_STRING MenuName;
@@ -2024,7 +1897,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
       }
    }
    else // Not a child
-      pWnd->IDMenu = (UINTCs->hMenu;
+      pWnd->IDMenu = (UINT_PTR)Cs->hMenu;
 
 
    if ( ParentWindow &&
@@ -2118,6 +1991,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    Class = IntGetAndReferenceClass(ClassName, Cs->hInstance, FALSE);
    if(!Class)
    {
+       EngSetLastError(ERROR_CANNOT_FIND_WND_CLASS);
        ERR("Failed to find class %wZ\n", ClassName);
        goto cleanup;
    }
@@ -2139,7 +2013,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
     }
     else if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
     {
-         ERR("Cannot create a child window without a parrent!\n");
+         ERR("Cannot create a child window without a parent!\n");
          EngSetLastError(ERROR_TLW_WITH_WSCHILD);
          goto cleanup;  /* WS_CHILD needs a parent, but WS_POPUP doesn't */
     }
@@ -2147,9 +2021,33 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
     ParentWindow = hWndParent ? UserGetWindowObject(hWndParent): NULL;
     OwnerWindow = hWndOwner ? UserGetWindowObject(hWndOwner): NULL;
 
-    /* FIXME: Is this correct? */
+    if (hWndParent && !ParentWindow)
+    {
+        ERR("Got invalid parent window handle\n");
+        goto cleanup;
+    }
+    else if (hWndOwner && !OwnerWindow)
+    {
+        ERR("Got invalid owner window handle\n");
+        ParentWindow = NULL;
+        goto cleanup;
+    }
+
     if(OwnerWindow)
-        OwnerWindow = UserGetAncestor(OwnerWindow, GA_ROOT);
+    {
+       if (IntIsDesktopWindow(OwnerWindow)) OwnerWindow = NULL;
+       else if (ParentWindow && !IntIsDesktopWindow(ParentWindow))
+       {
+          ERR("an owned window must be created as top-level\n");
+          EngSetLastError( STATUS_ACCESS_DENIED );
+          goto cleanup;
+       }
+       else /* owner must be a top-level window */
+       {
+          while ((OwnerWindow->style & (WS_POPUP|WS_CHILD)) == WS_CHILD && !IntIsDesktopWindow(OwnerWindow->spwndParent))
+                 OwnerWindow = OwnerWindow->spwndParent;
+       }
+    }
 
    /* Fix the position and the size of the window */
    if (ParentWindow)
@@ -2293,7 +2191,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
       if (ParentWindow != co_GetDesktopWindow(Window))
       {
          Cs->x += ParentWindow->rcClient.left;
-         Cs->y += ParentWindow->rcClient.top; 
+         Cs->y += ParentWindow->rcClient.top;
       }
    }
 
@@ -2314,19 +2212,19 @@ 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");
+      ERR("co_UserCreateWindowEx(): Offset rcWindow\n");
       RECTL_vOffsetRect(&Window->rcWindow,
                         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) && 
+      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);
@@ -2428,7 +2326,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    IntSendParentNotify(Window, WM_CREATE);
 
    /* Notify the shell that a new window was created */
-   if (Window->spwndParent == UserGetDesktopWindow() &&
+   if (UserIsDesktopWindow(Window->spwndParent) &&
        Window->spwndOwner == NULL &&
        (Window->style & WS_VISIBLE) &&
        (!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
@@ -2468,6 +2366,12 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
       }
    }
 
+   if (Class->atomClassName == gaGuiConsoleWndClass)
+   {
+       /* Count only console windows manually */
+       co_IntUserManualGuiCheck(TRUE);
+   }
+
    TRACE("co_UserCreateWindowEx(): Created window %p\n", hWnd);
    ret = Window;
 
@@ -2493,6 +2397,10 @@ cleanup:
    }
    if (ParentWindow) UserDerefObjectCo(ParentWindow);
 
+   // See CORE-13717, not setting error on success.
+   if (ret)
+      EngSetLastError(ERROR_SUCCESS);
+
    return ret;
 }
 
@@ -2575,25 +2483,29 @@ NtUserCreateWindowEx(
     NTSTATUS Status;
     LARGE_STRING lstrWindowName;
     LARGE_STRING lstrClassName;
+    LARGE_STRING lstrClsVersion;
     UNICODE_STRING ustrClassName;
+    UNICODE_STRING ustrClsVersion;
     CREATESTRUCTW Cs;
     HWND hwnd = NULL;
     PWND pwnd;
 
     lstrWindowName.Buffer = NULL;
     lstrClassName.Buffer = NULL;
+    lstrClsVersion.Buffer = NULL;
 
     ASSERT(plstrWindowName);
 
-    if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD) 
+    if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD)
     {
         /* check hMenu is valid handle */
-        if (hMenu && !ValidateHandle(hMenu, TYPE_MENU))
+        if (hMenu && !UserGetMenuObject(hMenu))
         {
-            /* error is set in ValidateHandle */
+            ERR("NtUserCreateWindowEx: Got an invalid menu handle!\n");
+            EngSetLastError(ERROR_INVALID_MENU_HANDLE);
             return NULL;
         }
-    } 
+    }
 
     /* Copy the window name to kernel mode */
     Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
@@ -2632,6 +2544,32 @@ NtUserCreateWindowEx(
         ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength, MAXUSHORT);
     }
 
+    /* Check if the class version is an atom */
+    if (IS_ATOM(plstrClsVersion))
+    {
+        /* It is, pass the atom in the UNICODE_STRING */
+        ustrClsVersion.Buffer = (PVOID)plstrClsVersion;
+        ustrClsVersion.Length = 0;
+        ustrClsVersion.MaximumLength = 0;
+    }
+    else
+    {
+        /* It's not, capture the class name */
+        Status = ProbeAndCaptureLargeString(&lstrClsVersion, plstrClsVersion);
+        if (!NT_SUCCESS(Status))
+        {
+            ERR("NtUserCreateWindowEx: failed to capture plstrClsVersion\n");
+            /* Set last error, cleanup and return */
+            SetLastNtError(Status);
+            goto cleanup;
+        }
+
+        /* We pass it on as a UNICODE_STRING */
+        ustrClsVersion.Buffer = lstrClsVersion.Buffer;
+        ustrClsVersion.Length = (USHORT)min(lstrClsVersion.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
+        ustrClsVersion.MaximumLength = (USHORT)min(lstrClsVersion.MaximumLength, MAXUSHORT);
+    }
+
     /* Fill the CREATESTRUCTW */
     /* we will keep here the original parameters */
     Cs.style = dwStyle;
@@ -2644,16 +2582,13 @@ NtUserCreateWindowEx(
     Cs.x = x;
     Cs.y = y;
     Cs.lpszName = (LPCWSTR) plstrWindowName->Buffer;
-    if (IS_ATOM(plstrClassName))
-       Cs.lpszClass = (LPCWSTR) plstrClassName;
-    else
-       Cs.lpszClass = (LPCWSTR) plstrClassName->Buffer;
+    Cs.lpszClass = ustrClassName.Buffer;
     Cs.dwExStyle = dwExStyle;
 
     UserEnterExclusive();
 
     /* Call the internal function */
-    pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer);
+    pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer);
 
     if(!pwnd)
     {
@@ -2672,24 +2607,29 @@ cleanup:
     {
         ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
     }
+    if (lstrClsVersion.Buffer)
+    {
+        ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
+    }
 
    return hwnd;
 }
 
 
-BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
+BOOLEAN co_UserDestroyWindow(PVOID Object)
 {
    HWND hWnd;
    PWND pwndTemp;
    PTHREADINFO ti;
    MSG msg;
+   PWND Window = Object;
 
    ASSERT_REFS_CO(Window); // FIXME: Temp HACK?
 
    hWnd = Window->head.h;
    ti = PsGetCurrentThreadWin32Thread();
 
-   TRACE("co_UserDestroyWindow \n");
+   TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
 
    /* Check for owner thread */
    if ( Window->head.pti != PsGetCurrentThreadWin32Thread())
@@ -2730,18 +2670,26 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
       IntSendParentNotify(Window, WM_DESTROY);
    }
 
-   /* Look whether the focus is within the tree of windows we will
-    * be destroying.
-    */
-   if (!co_WinPosShowWindow(Window, SW_HIDE))
-   {  // Rule #1.
-      if (ti->MessageQueue->spwndActive == Window && ti->MessageQueue == IntGetFocusMessageQueue())
+   if (!Window->spwndOwner && !IntGetParent(Window))
+   {
+      co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM) hWnd, 0);
+   }
+
+   /* Hide the window */
+   if (Window->style & WS_VISIBLE)
+   {
+      if (Window->style & WS_CHILD)
       {
-         co_WinPosActivateOtherWindow(Window);
+         /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
+         co_WinPosShowWindow(Window, SW_HIDE);
+      }
+      else
+      {
+         co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_HIDEWINDOW );
       }
    }
 
-   // Adjust last active.
+   /* Adjust last active */
    if ((pwndTemp = Window->spwndOwner))
    {
       while (pwndTemp->spwndOwner)
@@ -2751,7 +2699,7 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
          pwndTemp->spwndLastActive = Window->spwndOwner;
    }
 
-   if (Window->spwndParent && IntIsWindow(Window->head.h))
+   if (Window->spwndParent && IntIsWindow(UserHMGetHandle(Window)))
    {
       if ((Window->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
       {
@@ -2787,7 +2735,7 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
 
    IntEngWindowChanged(Window, WOC_DELETE);
 
-   if (!IntIsWindow(Window->head.h))
+   if (!IntIsWindow(UserHMGetHandle(Window)))
    {
       return TRUE;
    }
@@ -2852,7 +2800,12 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
     msg.pt = gpsi->ptCursor;
     co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
 
-   if (!IntIsWindow(Window->head.h))
+   IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
+
+   /* Send destroy messages */
+   IntSendDestroyMsg(UserHMGetHandle(Window));
+
+   if (!IntIsWindow(UserHMGetHandle(Window)))
    {
       return TRUE;
    }
@@ -2933,7 +2886,7 @@ IntFindWindow(PWND Parent,
          /* Do not send WM_GETTEXT messages in the kernel mode version!
             The user mode version however calls GetWindowText() which will
             send WM_GETTEXT messages to windows belonging to its processes */
-         if (!ClassAtom || Child->pcls->atomClassName == ClassAtom)
+         if (!ClassAtom || Child->pcls->atomNVClassName == ClassAtom)
          {
              // FIXME: LARGE_STRING truncated
              CurrentWindowName.Buffer = Child->strName.Buffer;
@@ -2943,11 +2896,11 @@ IntFindWindow(PWND Parent,
                 (Child->strName.Length < 0xFFFF &&
                  !RtlCompareUnicodeString(WindowName, &CurrentWindowName, TRUE)))
              {
-            Ret = Child->head.h;
-            break;
+                Ret = Child->head.h;
+                break;
+             }
          }
       }
-      }
       ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
    }
 
@@ -3017,6 +2970,7 @@ NtUserFindWindowEx(HWND hwndParent,
                if (!IntGetAtomFromStringOrAtom(&ClassName,
                                                &ClassAtom))
                {
+                   EngSetLastError(ERROR_CANNOT_FIND_WND_CLASS);
                    _SEH2_LEAVE;
                }
            }
@@ -3124,7 +3078,7 @@ NtUserFindWindowEx(HWND hwndParent,
                                 (TopLevelWindow->strName.Length < 0xFFFF &&
                                  !RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
                 ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
-                               ClassAtom == TopLevelWindow->pcls->atomClassName;
+                               ClassAtom == TopLevelWindow->pcls->atomNVClassName;
 
                 if (WindowMatches && ClassMatches)
                 {
@@ -3146,7 +3100,7 @@ NtUserFindWindowEx(HWND hwndParent,
        }
        else
        {
-          ERR("FindWindowEx: Not Desktop Parent!\n");
+          TRACE("FindWindowEx: Not Desktop Parent!\n");
           Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
        }
 
@@ -3327,12 +3281,7 @@ NtUserGetComboBoxInfo(
    }
    _SEH2_TRY
    {
-       if(pcbi)
-       {
-          ProbeForWrite(pcbi,
-                        sizeof(COMBOBOXINFO),
-                        1);
-       }
+        ProbeForWrite(pcbi, sizeof(COMBOBOXINFO), 1);
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
@@ -3380,7 +3329,7 @@ NtUserGetComboBoxInfo(
       SetLastNtError(_SEH2_GetExceptionCode());
    }
    _SEH2_END;
-   
+
    RETURN( Ret);
 
 CLEANUP:
@@ -3468,7 +3417,7 @@ NtUserGetListBoxInfo(
       SetLastNtError(_SEH2_GetExceptionCode());
    }
    _SEH2_END;
-   
+
    RETURN( Ret);
 
 CLEANUP:
@@ -3537,9 +3486,10 @@ HWND FASTCALL UserGetShellWindow(VOID)
    HWND Ret;
 
    NTSTATUS Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                     KernelMode,
+                     UserMode,
                      0,
-                     &WinStaObject);
+                     &WinStaObject,
+                     0);
 
    if (!NT_SUCCESS(Status))
    {
@@ -3580,15 +3530,16 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
       RETURN(FALSE);
    }
 
-   if(!(WndListView = UserGetWindowObject(hwndListView)))
+   if (!(WndListView = UserGetWindowObject(hwndListView)))
    {
       RETURN(FALSE);
    }
 
    Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                     KernelMode,
+                     UserMode,
                      0,
-                     &WinStaObject);
+                     &WinStaObject,
+                     0);
 
    if (!NT_SUCCESS(Status))
    {
@@ -3643,6 +3594,7 @@ NtUserSetShellWindowEx(HWND hwndShell, HWND hwndListView)
    {
        ti->pDeskInfo->hShellWindow = hwndShell;
        ti->pDeskInfo->spwndShell = WndShell;
+       ti->pDeskInfo->spwndBkGnd = WndListView;
        ti->pDeskInfo->ppiShellProcess = ti->ppi;
    }
 
@@ -3659,105 +3611,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-/*
- * NtUserGetSystemMenu
- *
- * The NtUserGetSystemMenu function allows the application to access the
- * window menu (also known as the system menu or the control menu) for
- * copying and modifying.
- *
- * Parameters
- *    hWnd
- *       Handle to the window that will own a copy of the window menu.
- *    bRevert
- *       Specifies the action to be taken. If this parameter is FALSE,
- *       NtUserGetSystemMenu returns a handle to the copy of the window menu
- *       currently in use. The copy is initially identical to the window menu
- *       but it can be modified.
- *       If this parameter is TRUE, GetSystemMenu resets the window menu back
- *       to the default state. The previous window menu, if any, is destroyed.
- *
- * Return Value
- *    If the bRevert parameter is FALSE, the return value is a handle to a
- *    copy of the window menu. If the bRevert parameter is TRUE, the return
- *    value is NULL.
- *
- * Status
- *    @implemented
- */
-
-HMENU APIENTRY
-NtUserGetSystemMenu(HWND hWnd, BOOL bRevert)
-{
-   PWND Window;
-   PMENU Menu;
-   DECLARE_RETURN(HMENU);
-
-   TRACE("Enter NtUserGetSystemMenu\n");
-   UserEnterShared();
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-      RETURN(NULL);
-   }
-
-   if (!(Menu = IntGetSystemMenu(Window, bRevert, FALSE)))
-   {
-      RETURN(NULL);
-   }
-
-   RETURN(Menu->head.h);
-
-CLEANUP:
-   TRACE("Leave NtUserGetSystemMenu, ret=%p\n", _ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-/*
- * NtUserSetSystemMenu
- *
- * Status
- *    @implemented
- */
-
-BOOL APIENTRY
-NtUserSetSystemMenu(HWND hWnd, HMENU hMenu)
-{
-   BOOL Result = FALSE;
-   PWND Window;
-   PMENU Menu;
-   DECLARE_RETURN(BOOL);
-
-   TRACE("Enter NtUserSetSystemMenu\n");
-   UserEnterExclusive();
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-      RETURN( FALSE);
-   }
-
-   if (hMenu)
-   {
-      /*
-       * Assign new menu handle.
-       */
-      if (!(Menu = UserGetMenuObject(hMenu)))
-      {
-         RETURN( FALSE);
-      }
-
-      Result = IntSetSystemMenu(Window, Menu);
-   }
-
-   RETURN( Result);
-
-CLEANUP:
-   TRACE("Leave NtUserSetSystemMenu, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
 // Fixes wine Win test_window_styles and todo tests...
 static BOOL FASTCALL
 IntCheckFrameEdge(ULONG Style, ULONG ExStyle)
@@ -3770,12 +3623,12 @@ IntCheckFrameEdge(ULONG Style, ULONG ExStyle)
       return FALSE;
 }
 
-LONG FASTCALL
-co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
+static LONG_PTR
+co_IntSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi, ULONG Size, BOOL bAlter)
 {
    PWND Window, Parent;
    PWINSTATION_OBJECT WindowStation;
-   LONG OldValue;
+   LONG_PTR OldValue;
    STYLESTRUCT Style;
 
    if (!(Window = UserGetWindowObject(hWnd)))
@@ -3785,29 +3638,53 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
 
    if ((INT)Index >= 0)
    {
-      if ((Index + sizeof(LONG)) > Window->cbwndExtra)
+      if ((Index + Size) > Window->cbwndExtra)
       {
          EngSetLastError(ERROR_INVALID_INDEX);
          return( 0);
       }
 
-      OldValue = *((LONG *)((PCHAR)(Window + 1) + Index));
-/*
-      if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
+#ifdef _WIN64
+      if (Size == sizeof(LONG))
       {
-         OldValue = (LONG)IntSetWindowProc( Wnd,
-                                           (WNDPROC)NewValue,
-                                            Ansi);
-         if (!OldValue) return 0;
+         OldValue = *((LONG *)((PCHAR)(Window + 1) + Index));
+         *((LONG*)((PCHAR)(Window + 1) + Index)) = (LONG)NewValue;
       }
-*/
-      *((LONG *)((PCHAR)(Window + 1) + Index)) = NewValue;
+      else
+#endif
+      {
+         OldValue = *((LONG_PTR *)((PCHAR)(Window + 1) + Index));
+         /*
+         if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
+         {
+            OldValue = (LONG_PTR)IntSetWindowProc( Wnd, (WNDPROC)NewValue, Ansi);
+            if (!OldValue) return 0;
+         }
+         */
+         *((LONG_PTR*)((PCHAR)(Window + 1) + Index)) = NewValue;
+      }
+
    }
    else
    {
+#ifdef _WIN64
+      if (Size == sizeof(LONG))
+      {
+         if ((Index != GWL_STYLE) &&
+             (Index != GWL_EXSTYLE) &&
+             (Index != GWL_ID) &&
+             (Index != GWL_USERDATA))
+         {
+            ERR("NtUserSetWindowLong(): Index requires pointer size: %lu\n", Index);
+            EngSetLastError(ERROR_INVALID_INDEX);
+            return 0;
+         }
+      }
+#endif
+
       switch (Index)
       {
-         case GWL_EXSTYLE:
+         case GWL_EXSTYLE: // LONG
             OldValue = (LONG) Window->ExStyle;
             Style.styleOld = OldValue;
             Style.styleNew = NewValue;
@@ -3829,24 +3706,58 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
             else
                Style.styleNew &= ~WS_EX_WINDOWEDGE;
 
+            if (!(Window->ExStyle & WS_EX_LAYERED))
+            {
+               SetLayeredStatus(Window, 0);
+            }
+
             Window->ExStyle = (DWORD)Style.styleNew;
+
             co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
             break;
 
-         case GWL_STYLE:
+         case GWL_STYLE: // LONG
             OldValue = (LONG) Window->style;
             Style.styleOld = OldValue;
             Style.styleNew = NewValue;
-            co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
 
-           /* WS_CLIPSIBLINGS can't be reset on top-level windows */
-            if (Window->spwndParent == UserGetDesktopWindow()) Style.styleNew |= WS_CLIPSIBLINGS;
+            if (!bAlter)
+                co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
+
+            /* WS_CLIPSIBLINGS can't be reset on top-level windows */
+            if (UserIsDesktopWindow(Window->spwndParent)) Style.styleNew |= WS_CLIPSIBLINGS;
+            /* WS_MINIMIZE can't be reset */
+            if (OldValue & WS_MINIMIZE) Style.styleNew |= WS_MINIMIZE;
             /* Fixes wine FIXME: changing WS_DLGFRAME | WS_THICKFRAME is supposed to change WS_EX_WINDOWEDGE too */
             if (IntCheckFrameEdge(NewValue, Window->ExStyle))
                Window->ExStyle |= WS_EX_WINDOWEDGE;
             else
                Window->ExStyle &= ~WS_EX_WINDOWEDGE;
 
+            if ((OldValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+            {
+               if ((NewValue & (WS_CHILD | WS_POPUP)) != WS_CHILD)
+               {
+                  //// From child to non-child it should be null already.
+                  ERR("IDMenu going null! %d\n",Window->IDMenu);
+                  Window->IDMenu = 0; // Window->spmenu = 0;
+               }
+            }
+            else
+            {
+               if ((NewValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+               {
+                  PMENU pMenu = UserGetMenuObject(UlongToHandle(Window->IDMenu));
+                  Window->state &= ~WNDS_HASMENU;
+                  if (pMenu)
+                  {
+                     ERR("IDMenu released 0x%p\n",pMenu);
+                     // ROS may not hold a lock after setting menu to window. But it should!
+                     //IntReleaseMenuObject(pMenu);
+                  }
+               }
+            }
+
             if ((Style.styleOld ^ Style.styleNew) & WS_VISIBLE)
             {
                if (Style.styleOld & WS_VISIBLE) Window->head.pti->cVisWindows--;
@@ -3854,10 +3765,12 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
                DceResetActiveDCEs( Window );
             }
             Window->style = (DWORD)Style.styleNew;
-            co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
+
+            if (!bAlter)
+                co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
             break;
 
-         case GWL_WNDPROC:
+         case GWLP_WNDPROC: // LONG_PTR
          {
             if ( Window->head.pti->ppi != PsGetCurrentProcessWin32Process() ||
                  Window->fnid & FNID_FREED)
@@ -3865,31 +3778,31 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
                EngSetLastError(ERROR_ACCESS_DENIED);
                return( 0);
             }
-            OldValue = (LONG)IntSetWindowProc(Window,
-                                              (WNDPROC)NewValue,
-                                              Ansi);
+            OldValue = (LONG_PTR)IntSetWindowProc(Window,
+                                                  (WNDPROC)NewValue,
+                                                  Ansi);
             break;
          }
 
-         case GWL_HINSTANCE:
-            OldValue = (LONG) Window->hModule;
+         case GWLP_HINSTANCE: // LONG_PTR
+            OldValue = (LONG_PTR) Window->hModule;
             Window->hModule = (HINSTANCE) NewValue;
             break;
 
-         case GWL_HWNDPARENT:
+         case GWLP_HWNDPARENT: // LONG_PTR
             Parent = Window->spwndParent;
             if (Parent && (Parent->head.h == IntGetDesktopWindow()))
-               OldValue = (LONG) IntSetOwner(Window->head.h, (HWND) NewValue);
+               OldValue = (LONG_PTR) IntSetOwner(Window->head.h, (HWND) NewValue);
             else
-               OldValue = (LONG) co_UserSetParent(Window->head.h, (HWND) NewValue);
+               OldValue = (LONG_PTR) co_UserSetParent(Window->head.h, (HWND) NewValue);
             break;
 
-         case GWL_ID:
+         case GWLP_ID: // LONG
             OldValue = (LONG) Window->IDMenu;
             Window->IDMenu = (UINT) NewValue;
             break;
 
-         case GWL_USERDATA:
+         case GWLP_USERDATA: // LONG or LONG_PTR
             OldValue = Window->dwUserData;
             Window->dwUserData = NewValue;
             break;
@@ -3905,6 +3818,18 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
    return( OldValue);
 }
 
+LONG FASTCALL
+co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
+{
+    return (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
+}
+
+LONG_PTR FASTCALL
+co_UserSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi)
+{
+    return co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
+}
+
 /*
  * NtUserSetWindowLong
  *
@@ -3919,25 +3844,69 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
 LONG APIENTRY
 NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
 {
-   DECLARE_RETURN(LONG);
+   LONG ret;
 
-   TRACE("Enter NtUserSetWindowLong\n");
    UserEnterExclusive();
 
    if (hWnd == IntGetDesktopWindow())
    {
       EngSetLastError(STATUS_ACCESS_DENIED);
-      RETURN( 0);
+      UserLeave();
+      return 0;
    }
 
-   RETURN( co_UserSetWindowLong(hWnd, Index, NewValue, Ansi));
+   ret = (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
 
-CLEANUP:
-   TRACE("Leave NtUserSetWindowLong, ret=%i\n",_ret_);
    UserLeave();
-   END_CLEANUP;
+
+   return ret;
 }
 
+#ifdef _WIN64
+LONG_PTR APIENTRY
+NtUserSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi)
+{
+    LONG_PTR ret;
+
+    UserEnterExclusive();
+
+    if (hWnd == IntGetDesktopWindow())
+    {
+        EngSetLastError(STATUS_ACCESS_DENIED);
+        UserLeave();
+        return 0;
+    }
+
+    ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
+
+    UserLeave();
+
+    return ret;
+}
+#endif // _WIN64
+
+DWORD APIENTRY
+NtUserAlterWindowStyle(HWND hWnd, DWORD Index, LONG NewValue)
+{
+   LONG ret;
+
+   UserEnterExclusive();
+
+   if (hWnd == IntGetDesktopWindow())
+   {
+      EngSetLastError(STATUS_ACCESS_DENIED);
+      UserLeave();
+      return 0;
+   }
+
+   ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, FALSE, sizeof(LONG), TRUE);
+
+   UserLeave();
+
+   return ret;
+}
+
+
 /*
  * NtUserSetWindowWord
  *
@@ -4016,7 +3985,7 @@ CLEANUP:
 /*
  * @implemented
  */
-DWORD APIENTRY
+DWORD_PTR APIENTRY
 NtUserQueryWindow(HWND hWnd, DWORD Index)
 {
 /* Console Leader Process CID Window offsets */
@@ -4024,7 +3993,7 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
 #define GWLP_CONSOLE_LEADER_TID 4
 
    PWND pWnd;
-   DWORD Result;
+   DWORD_PTR Result;
    DECLARE_RETURN(UINT);
 
    TRACE("Enter NtUserQueryWindow\n");
@@ -4043,11 +4012,11 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
               (pWnd->pcls->atomClassName == gaGuiConsoleWndClass) )
          {
             // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_PID)
-            Result = (DWORD)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
+            Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
          }
          else
          {
-            Result = (DWORD)IntGetWndProcessId(pWnd);
+            Result = (DWORD_PTR)IntGetWndProcessId(pWnd);
          }
          break;
       }
@@ -4058,29 +4027,29 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
               (pWnd->pcls->atomClassName == gaGuiConsoleWndClass) )
          {
             // IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_TID)
-            Result = (DWORD)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
+            Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
          }
          else
          {
-            Result = (DWORD)IntGetWndThreadId(pWnd);
+            Result = (DWORD_PTR)IntGetWndThreadId(pWnd);
          }
          break;
       }
 
       case QUERY_WINDOW_ACTIVE:
-         Result = (DWORD)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
+         Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
          break;
 
       case QUERY_WINDOW_FOCUS:
-         Result = (DWORD)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0);
+         Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0);
          break;
 
       case QUERY_WINDOW_ISHUNG:
-         Result = (DWORD)MsqIsHung(pWnd->head.pti);
+         Result = (DWORD_PTR)MsqIsHung(pWnd->head.pti);
          break;
 
       case QUERY_WINDOW_REAL_ID:
-         Result = (DWORD)pWnd->head.pti->pEThread->Cid.UniqueProcess;
+         Result = (DWORD_PTR)pWnd->head.pti->pEThread->Cid.UniqueProcess;
          break;
 
       case QUERY_WINDOW_FOREGROUND:
@@ -4088,7 +4057,7 @@ NtUserQueryWindow(HWND hWnd, DWORD Index)
          break;
 
       default:
-         Result = (DWORD)NULL;
+         Result = 0;
          break;
    }
 
@@ -4100,7 +4069,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-
 /*
  * @implemented
  */
@@ -4139,52 +4107,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-
-/*
- * @implemented
- */
-BOOL APIENTRY
-NtUserSetMenu(
-   HWND hWnd,
-   HMENU Menu,
-   BOOL Repaint)
-{
-   PWND Window;
-   BOOL Changed;
-   DECLARE_RETURN(BOOL);
-
-   TRACE("Enter NtUserSetMenu\n");
-   UserEnterExclusive();
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-      RETURN( FALSE);
-   }
-
-   if (! IntSetMenu(Window, Menu, &Changed))
-   {
-      RETURN( FALSE);
-   }
-
-   if (Changed && Repaint)
-   {
-      USER_REFERENCE_ENTRY Ref;
-
-      UserRefObjectCo(Window, &Ref);
-      co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
-                            SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
-
-      UserDerefObjectCo(Window);
-   }
-
-   RETURN( TRUE);
-
-CLEANUP:
-   TRACE("Leave NtUserSetMenu, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
 /*
  * @implemented
  */
@@ -4211,9 +4133,10 @@ NtUserSetWindowFNID(HWND hWnd,
 
    // From user land we only set these.
    if (fnID != FNID_DESTROY)
-   { //       Hacked so we can mark desktop~!
-      if ( (/*(fnID < FNID_BUTTON)*/ (fnID < FNID_FIRST) && (fnID > FNID_GHOST)) ||
-           Wnd->fnid != 0 )
+   {
+      /* HACK: The minimum should be FNID_BUTTON, but menu code relies on this */
+      if (fnID < FNID_FIRST || fnID > FNID_GHOST ||
+          Wnd->fnid != 0)
       {
          EngSetLastError(ERROR_INVALID_PARAMETER);
          RETURN( FALSE);
@@ -4229,6 +4152,78 @@ CLEANUP:
    END_CLEANUP;
 }
 
+BOOL APIENTRY
+DefSetText(PWND Wnd, PCWSTR WindowText)
+{
+   UNICODE_STRING UnicodeString;
+   BOOL Ret = FALSE;
+
+   RtlInitUnicodeString(&UnicodeString, WindowText);
+
+   if (UnicodeString.Length != 0)
+   {
+      if (Wnd->strName.MaximumLength > 0 &&
+          UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
+      {
+         ASSERT(Wnd->strName.Buffer != NULL);
+
+         Wnd->strName.Length = UnicodeString.Length;
+         Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
+         RtlCopyMemory(Wnd->strName.Buffer,
+                              UnicodeString.Buffer,
+                              UnicodeString.Length);
+      }
+      else
+      {
+         PWCHAR buf;
+         Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
+         buf = Wnd->strName.Buffer;
+         Wnd->strName.Buffer = NULL;
+         if (buf != NULL)
+         {
+            DesktopHeapFree(Wnd->head.rpdesk, buf);
+         }
+
+         Wnd->strName.Buffer = DesktopHeapAlloc(Wnd->head.rpdesk,
+                                                   UnicodeString.Length + sizeof(UNICODE_NULL));
+         if (Wnd->strName.Buffer != NULL)
+         {
+            Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
+            RtlCopyMemory(Wnd->strName.Buffer,
+                                 UnicodeString.Buffer,
+                                 UnicodeString.Length);
+            Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
+            Wnd->strName.Length = UnicodeString.Length;
+         }
+         else
+         {
+            EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto Exit;
+         }
+      }
+   }
+   else
+   {
+      Wnd->strName.Length = 0;
+      if (Wnd->strName.Buffer != NULL)
+          Wnd->strName.Buffer[0] = L'\0';
+   }
+
+   // FIXME: HAX! Windows does not do this in here!
+   // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
+   // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
+   /* Send shell notifications */
+   if (!Wnd->spwndOwner && !IntGetParent(Wnd))
+   {
+      co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) UserHMGetHandle(Wnd), FALSE); // FIXME Flashing?
+   }
+
+   Ret = TRUE;
+Exit:
+   if (UnicodeString.Buffer) RtlFreeUnicodeString(&UnicodeString);
+   return Ret;
+}
+
 /*
  * NtUserDefSetText
  *
@@ -4445,7 +4440,9 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
 //   ASSERT(OwnerWnd);
 
    TRACE("Enter ShowOwnedPopups Show: %s\n", (fShow ? "TRUE" : "FALSE"));
-   win_array = IntWinListChildren(OwnerWnd);
+
+   /* NOTE: Popups are not children */
+   win_array = IntWinListOwnedPopups(OwnerWnd);
 
    if (!win_array)
       return TRUE;
@@ -4468,6 +4465,7 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
              * regardless of the state of the owner
              */
             co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
+            pWnd->state &= ~WNDS_HIDDENPOPUP;
             continue;
          }
       }
@@ -4480,10 +4478,10 @@ IntShowOwnedPopups(PWND OwnerWnd, BOOL fShow )
              * regardless of the state of the owner
              */
             co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
+            pWnd->state |= WNDS_HIDDENPOPUP;
             continue;
          }
       }
-
    }
    ExFreePoolWithTag(win_array, USERTAG_WINDOWLIST);
    TRACE("Leave ShowOwnedPopups\n");