[WIN32K:NTUSER]
[reactos.git] / reactos / win32ss / user / ntuser / window.c
index 66e858f..24e8cd8 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 );
     }
@@ -340,7 +345,7 @@ IntGetWindow(HWND hWnd,
                 if (Wnd->spwndPrev != NULL)
                     FoundWnd = Wnd->spwndPrev;
                 break;
-   
+
             case GW_CHILD:
                 if (Wnd->spwndChild != NULL)
                     FoundWnd = Wnd->spwndChild;
@@ -362,6 +367,20 @@ 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;
+}
+
 /***********************************************************************
  *           IntSendDestroyMsg
  */
@@ -379,17 +398,29 @@ static void IntSendDestroyMsg(HWND hWnd)
        * be destroying.
        */
       // Rule #1
-      if ( ti->MessageQueue->spwndActive == Window ||
+      if ( ti->MessageQueue->spwndActive == Window || // Fixes CORE-106 RegSvr32 exit and return focus to CMD.
           (ti->MessageQueue->spwndActive == NULL && ti->MessageQueue == IntGetFocusMessageQueue()) )
       {
          co_WinPosActivateOtherWindow(Window);
       }
 
-      if (ti->MessageQueue->CaretInfo->hWnd == UserHMGetHandle(Window))
+      /* Fixes CMD properties closing and returning focus to CMD */
+      if (ti->MessageQueue->spwndFocus == Window)
       {
-         co_IntDestroyCaret(ti);
+         if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+         {
+            co_UserSetFocus(Window->spwndParent);
+         }
+         else
+         {
+            co_UserSetFocus(NULL);
+         }
       }
 
+      if (ti->MessageQueue->CaretInfo.hWnd == UserHMGetHandle(Window))
+      {
+         co_IntDestroyCaret(ti);
+      }
    }
 
    /*
@@ -548,15 +579,40 @@ LRESULT co_UserFreeWindow(PWND Window,
          ThreadData->rpdesk->rpwinstaParent->ShellListView = NULL;
    }
 
+   /* Fixes dialog test_focus breakage due to r66237. */
+   if (ThreadData->MessageQueue->spwndFocus == Window)
+      ThreadData->MessageQueue->spwndFocus = NULL;
+
+   if (ThreadData->MessageQueue->spwndActive == Window)
+      ThreadData->MessageQueue->spwndActive = NULL;
+
    if (ThreadData->MessageQueue->spwndCapture == Window)
    {
       IntReleaseCapture();
    }
 
+   //// 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))
+      {
+         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)))
    {
+      TRACE("UFW: IDMenu %p\n",Window->IDMenu);
       IntDestroyMenuObject(Menu, TRUE);
       Window->IDMenu = 0;
    }
@@ -574,8 +630,8 @@ LRESULT co_UserFreeWindow(PWND 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);
    }
 
@@ -591,6 +647,7 @@ LRESULT co_UserFreeWindow(PWND Window,
    }
 
    /* dereference the class */
+   NT_ASSERT(Window->head.pti != NULL);
    IntDereferenceClass(Window->pcls,
                        Window->head.pti->pDeskInfo,
                        Window->head.pti->ppi);
@@ -757,99 +814,28 @@ 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 ******************************************************************/
 
-
+////
+//   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
@@ -1151,7 +1137,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);
@@ -1392,7 +1378,7 @@ 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;
       }
 
@@ -1431,7 +1417,8 @@ NtUserBuildHwndList(
                dwCount++;
             }
          }
-      }      
+         ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
+      }
 
       ObDereferenceObject(Thread);
    }
@@ -1443,7 +1430,7 @@ NtUserBuildHwndList(
 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 (VerifyWnd(pWindow->spwndParent) && pWindow->spwndParent != UserGetDesktopWindow())
         {
@@ -1652,7 +1639,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    }
 
    pWnd->head.pti->cWindows++;
-#ifdef NEW_CURSORICON
+
    if (Class->spicn && !Class->spicnSm)
    {
        HICON IconSmHandle = NULL;
@@ -1683,16 +1670,6 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
            Class->CSF_flags |= CSF_CACHEDSMICON;
        }
    }
-#else
-   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;
-   }
-#endif
 
    if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC)
       pWnd->state |= WNDS_SERVERSIDEWINDOWPROC;
@@ -2116,7 +2093,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;
       }
    }
 
@@ -2149,7 +2126,7 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs,
    /* 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);
@@ -2414,7 +2391,7 @@ NtUserCreateWindowEx(
 
     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 && !UserGetMenuObject(hMenu))
@@ -2423,7 +2400,7 @@ NtUserCreateWindowEx(
             EngSetLastError(ERROR_INVALID_MENU_HANDLE);
             return NULL;
         }
-    } 
+    }
 
     /* Copy the window name to kernel mode */
     Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
@@ -2474,10 +2451,7 @@ 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();
@@ -2566,10 +2540,12 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
       co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM) hWnd, 0);
    }
 
+   /* Hide the window */
    if (Window->style & WS_VISIBLE)
    {
       if (Window->style & WS_CHILD)
       {
+         /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
          co_WinPosShowWindow(Window, SW_HIDE);
       }
       else
@@ -2786,11 +2762,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);
    }
 
@@ -3170,12 +3146,7 @@ NtUserGetComboBoxInfo(
    }
    _SEH2_TRY
    {
-       if(pcbi)
-       {
-          ProbeForWrite(pcbi,
-                        sizeof(COMBOBOXINFO),
-                        1);
-       }
+        ProbeForWrite(pcbi, sizeof(COMBOBOXINFO), 1);
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
@@ -3223,7 +3194,7 @@ NtUserGetComboBoxInfo(
       SetLastNtError(_SEH2_GetExceptionCode());
    }
    _SEH2_END;
-   
+
    RETURN( Ret);
 
 CLEANUP:
@@ -3311,7 +3282,7 @@ NtUserGetListBoxInfo(
       SetLastNtError(_SEH2_GetExceptionCode());
    }
    _SEH2_END;
-   
+
    RETURN( Ret);
 
 CLEANUP:
@@ -3516,8 +3487,8 @@ IntCheckFrameEdge(ULONG Style, ULONG ExStyle)
       return FALSE;
 }
 
-LONG FASTCALL
-co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
+static LONG
+co_IntSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi, BOOL bAlter)
 {
    PWND Window, Parent;
    PWINSTATION_OBJECT WindowStation;
@@ -3546,7 +3517,7 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
                                             Ansi);
          if (!OldValue) return 0;
       }
-*/
+ */
       *((LONG *)((PCHAR)(Window + 1) + Index)) = NewValue;
    }
    else
@@ -3575,7 +3546,13 @@ 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;
 
@@ -3583,7 +3560,9 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
             OldValue = (LONG) Window->style;
             Style.styleOld = OldValue;
             Style.styleNew = NewValue;
-            co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
+
+            if (!bAlter)
+                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;
@@ -3600,7 +3579,9 @@ 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:
@@ -3651,6 +3632,13 @@ 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 co_IntSetWindowLong(hWnd, Index, NewValue, Ansi, FALSE);
+}
+
 /*
  * NtUserSetWindowLong
  *
@@ -3665,25 +3653,46 @@ 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 = co_IntSetWindowLong(hWnd, Index, NewValue, Ansi, FALSE);
 
-CLEANUP:
-   TRACE("Leave NtUserSetWindowLong, ret=%i\n",_ret_);
    UserLeave();
-   END_CLEANUP;
+
+   return ret;
+}
+
+DWORD APIENTRY
+NtUserAlterWindowStyle(HWND hWnd, DWORD Index, LONG NewValue)
+{
+   LONG ret;
+
+   UserEnterExclusive();
+
+   if (hWnd == IntGetDesktopWindow())
+   {
+      EngSetLastError(STATUS_ACCESS_DENIED);
+      UserLeave();
+      return 0;
+   }
+
+   ret = co_IntSetWindowLong(hWnd, Index, NewValue, FALSE, TRUE);
+
+   UserLeave();
+
+   return ret;
 }
 
+
 /*
  * NtUserSetWindowWord
  *
@@ -3846,7 +3855,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-
 /*
  * @implemented
  */
@@ -3885,52 +3893,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
  */
@@ -3957,9 +3919,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);
@@ -3975,6 +3938,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
  *