Apply changes from r42521 to DefWndProcW as well
[reactos.git] / reactos / dll / win32 / user32 / windows / defwnd.c
index 5f2cd55..e6ef792 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id$
+/*
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS user32.dll
@@ -12,8 +12,9 @@
 /* INCLUDES ******************************************************************/
 
 #include <user32.h>
-#define NDEBUG
-#include <debug.h>
+
+#include <wine/debug.h>
+WINE_DEFAULT_DEBUG_CHANNEL(user32);
 
 #ifndef WM_SETVISIBLE
 #define WM_SETVISIBLE 9
@@ -32,12 +33,12 @@ void FASTCALL MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG
 
 /* GLOBALS *******************************************************************/
 
-COLORREF SysColors[NUM_SYSCOLORS] = {0};
-HPEN SysPens[NUM_SYSCOLORS] = {0};
-HBRUSH SysBrushes[NUM_SYSCOLORS] = {0};
-
 /* Bits in the dwKeyData */
-#define KEYDATA_ALT   0x2000
+#define KEYDATA_ALT             0x2000
+#define KEYDATA_PREVSTATE       0x4000
+
+static short iF10Key = 0;
+static short iMenuSysKey = 0;
 
 /* FUNCTIONS *****************************************************************/
 
@@ -50,24 +51,19 @@ InitStockObjects(void)
              we should rather map the table into usermode. But it only affects the
              SysColors table - the pens, brushes and stock objects are not affected
              as their handles never change. But it'd be faster to map them, too. */
-  if(SysBrushes[0] == NULL)
-  {
-    /* only initialize once */
-    (void)NtUserGetSysColors(SysColors, NUM_SYSCOLORS);
-    (void)NtUserGetSysColorPens(SysPens, NUM_SYSCOLORS);
-    (void)NtUserGetSysColorBrushes(SysBrushes, NUM_SYSCOLORS);
-  }
+
+ // Done! g_psi!
 }
 
 /*
  * @implemented
  */
-DWORD STDCALL
+DWORD WINAPI
 GetSysColor(int nIndex)
 {
-  if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
+  if(nIndex >= 0 && nIndex < NUM_SYSCOLORS)
   {
-    return SysColors[nIndex];
+    return g_psi->argbSystem[nIndex];
   }
 
   SetLastError(ERROR_INVALID_PARAMETER);
@@ -77,27 +73,12 @@ GetSysColor(int nIndex)
 /*
  * @implemented
  */
-HPEN STDCALL
-GetSysColorPen(int nIndex)
-{
-  if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
-  {
-    return SysPens[nIndex];
-  }
-
-  SetLastError(ERROR_INVALID_PARAMETER);
-  return NULL;
-}
-
-/*
- * @implemented
- */
-HBRUSH STDCALL
+HBRUSH WINAPI
 GetSysColorBrush(int nIndex)
 {
-  if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
+  if(nIndex >= 0 && nIndex < NUM_SYSCOLORS)
   {
-    return SysBrushes[nIndex];
+    return g_psi->ahbrSystem[nIndex];
   }
 
   SetLastError(ERROR_INVALID_PARAMETER);
@@ -108,53 +89,43 @@ GetSysColorBrush(int nIndex)
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetSysColors(
   int cElements,
   CONST INT *lpaElements,
   CONST COLORREF *lpaRgbValues)
 {
-  BOOL Ret;
-  struct
-  {
-    INT *Elements;
-    COLORREF *Colors;
-  } ChangeSysColors;
+  return NtUserSetSysColors(cElements, lpaElements, lpaRgbValues, 0);
+}
 
-  ChangeSysColors.Elements = (INT*)lpaElements;
-  ChangeSysColors.Colors = (COLORREF*)lpaRgbValues;
+BOOL
+FASTCALL
+DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi)
+{
+  LARGE_STRING lsString;
 
-  if(cElements > 0)
+  if ( String )
   {
-    Ret = NtUserSetSysColors(&ChangeSysColors, cElements);
-    if(Ret)
-    {
-      /* FIXME - just change it in the usermode structure, too, instead of asking win32k again */
-      (void)NtUserGetSysColors(SysColors, NUM_SYSCOLORS);
-    }
-  }
-  else
-  {
-    SetLastError(ERROR_INVALID_PARAMETER);
-    Ret = FALSE;
+     if ( Ansi )
+        RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&lsString, (PCSZ)String, 0);
+     else
+        RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&lsString, String, 0);
   }
-
-  return Ret;
+  return NtUserDefSetText(hWnd, (String ? &lsString : NULL));
 }
 
 void
-UserGetInsideRectNC(HWND hWnd, RECT *rect)
+UserGetInsideRectNC(PWND Wnd, RECT *rect)
 {
-    RECT WindowRect;
     ULONG Style;
     ULONG ExStyle;
 
-    Style = GetWindowLongW(hWnd, GWL_STYLE);
-    ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
-    GetWindowRect(hWnd, &WindowRect);
+    Style = Wnd->style;
+    ExStyle = Wnd->ExStyle;
+
     rect->top    = rect->left = 0;
-    rect->right  = WindowRect.right - WindowRect.left;
-    rect->bottom = WindowRect.bottom - WindowRect.top;
+    rect->right  = Wnd->rcWindow.right - Wnd->rcWindow.left;
+    rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
 
     if (Style & WS_ICONIC)
     {
@@ -192,12 +163,25 @@ UserGetInsideRectNC(HWND hWnd, RECT *rect)
 VOID
 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
 {
-  if ((BOOL) wParam && 0 == (GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE))
+    LONG Style = GetWindowLongPtr(hWnd, GWL_STYLE);
+    /* Content can be redrawn after a change. */
+    if (wParam)
     {
-      ShowWindow(hWnd, SW_NORMAL);
+       if (!(Style & WS_VISIBLE)) /* Not Visible */
+       {
+          SetWindowLongPtr(hWnd, GWL_STYLE, WS_VISIBLE);
+       }
     }
-
-  UNIMPLEMENTED;
+    else /* Content cannot be redrawn after a change. */
+    {
+       if (Style & WS_VISIBLE) /* Visible */
+       {
+            RedrawWindow( hWnd, NULL, 0, RDW_ALLCHILDREN | RDW_VALIDATE );
+            Style &= ~WS_VISIBLE;
+            SetWindowLongPtr(hWnd, GWL_STYLE, Style); /* clear bits */
+       }
+    }
+    return;
 }
 
 
@@ -225,7 +209,7 @@ DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam, ULONG Style)
 
     case HTCLIENT:
       {
-       HICON hCursor = (HICON)GetClassLongW(hWnd, GCL_HCURSOR);
+       HICON hCursor = (HICON)GetClassLongPtrW(hWnd, GCL_HCURSOR);
        if (hCursor)
          {
            SetCursor(hCursor);
@@ -267,7 +251,7 @@ DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam, ULONG Style)
     case HTBOTTOMLEFT:
     case HTTOPRIGHT:
       {
-        if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MAXIMIZE)
+        if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MAXIMIZE)
         {
           break;
         }
@@ -278,21 +262,21 @@ DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam, ULONG Style)
 }
 
 static LONG
-DefWndStartSizeMove(HWND hWnd, WPARAM wParam, POINT *capturePoint)
+DefWndStartSizeMove(HWND hWnd, PWND Wnd, WPARAM wParam, POINT *capturePoint)
 {
   LONG hittest = 0;
   POINT pt;
   MSG msg;
   RECT rectWindow;
-  ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
+  ULONG Style = Wnd->style;
 
-  GetWindowRect(hWnd, &rectWindow);
+  rectWindow = Wnd->rcWindow;
 
   if ((wParam & 0xfff0) == SC_MOVE)
     {
       /* Move pointer at the center of the caption */
       RECT rect;
-      UserGetInsideRectNC(hWnd, &rect);
+      UserGetInsideRectNC(Wnd, &rect);
       if (Style & WS_SYSMENU)
        rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
       if (Style & WS_MINIMIZEBOX)
@@ -418,14 +402,22 @@ DefWndDoSizeMove(HWND hwnd, WORD wParam)
   HCURSOR hDragCursor = 0, hOldCursor = 0;
   POINT minTrack, maxTrack;
   POINT capturePoint, pt;
-  ULONG Style = GetWindowLongW(hwnd, GWL_STYLE);
-  ULONG ExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
+  ULONG Style, ExStyle;
   BOOL thickframe;
-  BOOL iconic = Style & WS_MINIMIZE;
+  BOOL iconic;
   BOOL moved = FALSE;
   DWORD dwPoint = GetMessagePos();
   BOOL DragFullWindows = FALSE;
   HWND hWndParent = NULL;
+  PWND Wnd;
+
+  Wnd = ValidateHwnd(hwnd);
+  if (!Wnd)
+      return;
+
+  Style = Wnd->style;
+  ExStyle = Wnd->ExStyle;
+  iconic = (Style & WS_MINIMIZE) != 0;
 
   SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
 
@@ -433,7 +425,7 @@ DefWndDoSizeMove(HWND hwnd, WORD wParam)
   pt.y = GET_Y_LPARAM(dwPoint);
   capturePoint = pt;
 
-  if (IsZoomed(hwnd) || !IsWindowVisible(hwnd))
+  if ((Style & WS_MAXIMIZE) || !IsWindowVisible(hwnd))
     {
       return;
     }
@@ -443,7 +435,7 @@ DefWndDoSizeMove(HWND hwnd, WORD wParam)
     {
       if (!hittest)
        {
-         hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
+         hittest = DefWndStartSizeMove(hwnd, Wnd, wParam, &capturePoint);
        }
       if (!hittest)
        {
@@ -463,7 +455,7 @@ DefWndDoSizeMove(HWND hwnd, WORD wParam)
       else
        {
          SetCapture(hwnd);
-         hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
+         hittest = DefWndStartSizeMove(hwnd, Wnd, wParam, &capturePoint);
          if (!hittest)
            {
              ReleaseCapture();
@@ -475,7 +467,7 @@ DefWndDoSizeMove(HWND hwnd, WORD wParam)
   /* Get min/max info */
 
   WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
-  GetWindowRect(hwnd, &sizingRect);
+  sizingRect = Wnd->rcWindow;
   if (Style & WS_CHILD)
     {
       hWndParent = GetParent(hwnd);
@@ -547,7 +539,7 @@ DefWndDoSizeMove(HWND hwnd, WORD wParam)
 
   if( iconic ) /* create a cursor for dragging */
     {
-      HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
+      HICON hIcon = (HICON)GetClassLongPtrW(hwnd, GCL_HICON);
       if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
       if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
       if( !hDragCursor ) iconic = FALSE;
@@ -675,6 +667,14 @@ DefWndDoSizeMove(HWND hwnd, WORD wParam)
       DeleteObject(DesktopRgn);
     }
   }
+//#if 0
+//  if (ISITHOOKED(WH_CBT))
+  {
+      LRESULT lResult;
+      NtUserMessageCall( hwnd, WM_CBT, HCBT_MOVESIZE, (LPARAM)&sizingRect, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
+      if (lResult) moved = FALSE;
+  }
+//#endif
   (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, NULL);
   SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
   SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
@@ -749,10 +749,21 @@ DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
 
 
 LRESULT
-DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
+DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
 {
   WINDOWPLACEMENT wp;
+  POINT Pt;
 
+  if (!IsWindowEnabled( hWnd )) return 0;
+
+//#if 0
+//  if (ISITHOOKED(WH_CBT))
+  {
+     LRESULT lResult;
+     NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
+     if (lResult) return 0;
+  }
+//#endif
   switch (wParam & 0xfff0)
     {
       case SC_MOVE:
@@ -784,17 +795,25 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
         }
         break;
       case SC_CLOSE:
-        SendMessageA(hWnd, WM_CLOSE, 0, 0);
-        break;
+        return SendMessageW(hWnd, WM_CLOSE, 0, 0);
+
       case SC_MOUSEMENU:
-        MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
+        {
+          Pt.x = (short)LOWORD(lParam);
+          Pt.y = (short)HIWORD(lParam);
+          MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
+        }
        break;
       case SC_KEYMENU:
-        MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
+        MenuTrackKbdMenuBar(hWnd, wParam, (WCHAR)lParam);
        break;
       case SC_VSCROLL:
       case SC_HSCROLL:
-        DefWndTrackScrollBar(hWnd, wParam, Pt);
+        {
+          Pt.x = (short)LOWORD(lParam);
+          Pt.y = (short)HIWORD(lParam);
+          DefWndTrackScrollBar(hWnd, wParam, Pt);
+        }
        break;
 
       default:
@@ -810,7 +829,7 @@ LRESULT
 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
 {
     POINT maxTrack, minTrack;
-    LONG style = GetWindowLongA(hWnd, GWL_STYLE);
+    LONG style = GetWindowLongPtrA(hWnd, GWL_STYLE);
 
     if (Pos->flags & SWP_NOSIZE) return 0;
     if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
@@ -842,7 +861,7 @@ DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
   RECT Rect;
 
   GetClientRect(hWnd, &Rect);
-  MapWindowPoints(hWnd, (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD ?
+  MapWindowPoints(hWnd, (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD ?
                          GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
 
   if (! (Pos->flags & SWP_NOCLIENTMOVE))
@@ -922,13 +941,84 @@ DefWndControlColor(HDC hDC, UINT ctlType)
   return GetSysColorBrush(COLOR_WINDOW);
 }
 
+static void DefWndPrint( HWND hwnd, HDC hdc, ULONG uFlags)
+{
+  /*
+   * Visibility flag.
+   */
+  if ( (uFlags & PRF_CHECKVISIBLE) &&
+       !IsWindowVisible(hwnd) )
+      return;
+
+  /*
+   * Unimplemented flags.
+   */
+  if ( (uFlags & PRF_CHILDREN) ||
+       (uFlags & PRF_OWNED)    ||
+       (uFlags & PRF_NONCLIENT) )
+  {
+    FIXME("WM_PRINT message with unsupported flags\n");
+  }
+
+  /*
+   * Background
+   */
+  if ( uFlags & PRF_ERASEBKGND)
+    SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
+
+  /*
+   * Client area
+   */
+  if ( uFlags & PRF_CLIENT)
+    SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, uFlags);
+}
+
+static BOOL CALLBACK
+UserSendUiUpdateMsg(HWND hwnd, LPARAM lParam)
+{
+    SendMessageW(hwnd, WM_UPDATEUISTATE, (WPARAM)lParam, 0);
+    return TRUE;
+}
+
+
 VOID FASTCALL
 DefWndScreenshot(HWND hWnd)
 {
+    RECT rect;
+    HDC hdc;
+    INT w;
+    INT h;
+    HBITMAP hbitmap;
+    HDC hdc2;
+
+    OpenClipboard(hWnd);
+    EmptyClipboard();
+
+    hdc = GetWindowDC(hWnd);
+    GetWindowRect(hWnd, &rect);
+    w = rect.right - rect.left;
+    h = rect.bottom - rect.top;
+
+    hbitmap = CreateCompatibleBitmap(hdc, w, h);
+    hdc2 = CreateCompatibleDC(hdc);
+    SelectObject(hdc2, hbitmap);
+
+    BitBlt(hdc2, 0, 0, w, h,
+           hdc, 0, 0,
+           SRCCOPY);
+
+    SetClipboardData(CF_BITMAP, hbitmap);
+
+    ReleaseDC(hWnd, hdc);
+    ReleaseDC(hWnd, hdc2);
+
+    CloseClipboard();
 
 }
 
-LRESULT STDCALL
+
+
+LRESULT WINAPI
 User32DefWindowProc(HWND hWnd,
                    UINT Msg,
                    WPARAM wParam,
@@ -947,6 +1037,18 @@ User32DefWindowProc(HWND hWnd,
             return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
         }
 
+        case WM_POPUPSYSTEMMENU:
+        {
+            /* This is an undocumented message used by the windows taskbar to
+               display the system menu of windows that belong to other processes. */
+            HMENU menu = GetSystemMenu(hWnd, FALSE);
+
+            if (menu)
+                TrackPopupMenu(menu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
+                               LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
+            return 0;
+        }
+
         case WM_NCACTIVATE:
         {
             return DefWndNCActivate(hWnd, wParam);
@@ -960,11 +1062,20 @@ User32DefWindowProc(HWND hWnd,
             return (DefWndNCHitTest(hWnd, Point));
         }
 
+        case WM_LBUTTONDOWN:
+        case WM_RBUTTONDOWN:
+        case WM_MBUTTONDOWN:
+            iF10Key = iMenuSysKey = 0;
+            break;
+
         case WM_NCLBUTTONDOWN:
         {
             return (DefWndNCLButtonDown(hWnd, wParam, lParam));
         }
 
+        case WM_LBUTTONDBLCLK:
+            return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));
+
         case WM_NCLBUTTONDBLCLK:
         {
             return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
@@ -980,6 +1091,16 @@ User32DefWindowProc(HWND hWnd,
             return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
         }
 
+        case WM_NCRBUTTONDOWN:
+        {
+            /* in Windows, capture is taken when right-clicking on the caption bar */
+            if (wParam == HTCAPTION)
+            {
+                SetCapture(hWnd);
+            }
+            break;
+        }
+
         case WM_RBUTTONUP:
         {
             POINT Pt;
@@ -1002,9 +1123,18 @@ User32DefWindowProc(HWND hWnd,
             break;
         }
 
+        case WM_NCRBUTTONUP:
+          /*
+           * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
+           * in Windows), but what _should_ we do? According to MSDN :
+           * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
+           * message to the window". When is it appropriate?
+           */
+            break;
+
         case WM_CONTEXTMENU:
         {
-            if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
+            if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
             {
                 if (bUnicode)
                 {
@@ -1018,10 +1148,10 @@ User32DefWindowProc(HWND hWnd,
             else
             {
                 POINT Pt;
-                DWORD Style;
+                LONG_PTR Style;
                 LONG HitCode;
 
-                Style = GetWindowLongW(hWnd, GWL_STYLE);
+                Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
 
                 Pt.x = GET_X_LPARAM(lParam);
                 Pt.y = GET_Y_LPARAM(lParam);
@@ -1039,8 +1169,8 @@ User32DefWindowProc(HWND hWnd,
 
                     if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
                     {
-                      MenuInitSysMenuPopup(SystemMenu, GetWindowLongW(hWnd, GWL_STYLE),
-                                           GetClassLongW(hWnd, GCL_STYLE), HitCode);
+                      MenuInitSysMenuPopup(SystemMenu, GetWindowLongPtrW(hWnd, GWL_STYLE),
+                                           GetClassLongPtrW(hWnd, GCL_STYLE), HitCode);
 
                       if(HitCode == HTCAPTION)
                         Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
@@ -1057,7 +1187,19 @@ User32DefWindowProc(HWND hWnd,
 
         case WM_PRINT:
         {
-            /* FIXME: Implement. */
+            DefWndPrint(hWnd, (HDC)wParam, lParam);
+            return (0);
+        }
+
+        case WM_SYSCOLORCHANGE:
+        {
+            /* force to redraw non-client area */
+            DefWndNCPaint(hWnd, (HRGN)1, -1);
+            /* Use InvalidateRect to redraw client area, enable
+             * erase to redraw all subcontrols otherwise send the
+             * WM_SYSCOLORCHANGE to child windows/controls is required
+             */
+            InvalidateRect(hWnd,NULL,TRUE);
             return (0);
         }
 
@@ -1069,8 +1211,9 @@ User32DefWindowProc(HWND hWnd,
             if (hDC)
             {
                 HICON hIcon;
-                if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
-                    (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
+
+                if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
+                    (hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON)) != NULL)
                 {
                     RECT ClientRect;
                     INT x, y;
@@ -1102,7 +1245,14 @@ User32DefWindowProc(HWND hWnd,
 
         case WM_SETREDRAW:
         {
-            DefWndSetRedraw(hWnd, wParam);
+            LONG_PTR Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
+            if (wParam) SetWindowLongPtr(hWnd, GWL_STYLE, Style | WS_VISIBLE);
+            else
+            {
+                RedrawWindow(hWnd, NULL, 0, RDW_ALLCHILDREN | RDW_VALIDATE);
+                Style &= ~WS_VISIBLE;
+                SetWindowLongPtr(hWnd, GWL_STYLE, Style);
+            }
             return (0);
         }
 
@@ -1114,7 +1264,7 @@ User32DefWindowProc(HWND hWnd,
 
         case WM_MOUSEACTIVATE:
         {
-            if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
+            if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
             {
                 LONG Ret;
                 if (bUnicode)
@@ -1139,7 +1289,7 @@ User32DefWindowProc(HWND hWnd,
         {
             /* Check if the window is minimized. */
             if (LOWORD(wParam) != WA_INACTIVE &&
-                !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
+                !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE))
             {
                 SetFocus(hWnd);
             }
@@ -1148,7 +1298,7 @@ User32DefWindowProc(HWND hWnd,
 
         case WM_MOUSEWHEEL:
         {
-            if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
+            if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
             {
                 if (bUnicode)
                 {
@@ -1168,13 +1318,13 @@ User32DefWindowProc(HWND hWnd,
         case WM_ICONERASEBKGND:
         {
             RECT Rect;
-            HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
+            HBRUSH hBrush = (HBRUSH)GetClassLongPtrW(hWnd, GCL_HBRBACKGROUND);
 
             if (NULL == hBrush)
             {
                 return 0;
             }
-            if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
+            if (GetClassLongPtrW(hWnd, GCL_STYLE) & CS_PARENTDC)
             {
                 /* can't use GetClipBox with a parent DC or we fill the whole parent */
                 GetClientRect(hWnd, &Rect);
@@ -1197,9 +1347,12 @@ User32DefWindowProc(HWND hWnd,
         case WM_CTLCOLORSCROLLBAR:
            return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
 
+        case WM_CTLCOLOR:
+            return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
+
         case WM_SETCURSOR:
         {
-            ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
+            LONG_PTR Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
 
             if (Style & WS_CHILD)
             {
@@ -1226,30 +1379,34 @@ User32DefWindowProc(HWND hWnd,
         }
 
         case WM_SYSCOMMAND:
-        {
-            POINT Pt;
-            Pt.x = GET_X_LPARAM(lParam);
-            Pt.y = GET_Y_LPARAM(lParam);
-            return (DefWndHandleSysCommand(hWnd, wParam, Pt));
-        }
+            return (DefWndHandleSysCommand(hWnd, wParam, lParam));
 
-        /* FIXME: Handle key messages. */
-/*
         case WM_KEYDOWN:
-        case WM_KEYUP:
-        case WM_SYSKEYUP:
-        case WM_SYSCHAR:
-*/
+            if(wParam == VK_F10) iF10Key = VK_F10;
+            break;
 
         /* FIXME: This is also incomplete. */
         case WM_SYSKEYDOWN:
         {
             if (HIWORD(lParam) & KEYDATA_ALT)
             {
+                HWND top = GetAncestor(hWnd, GA_ROOT);
+             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
+                if ( (wParam == VK_MENU || wParam == VK_LMENU
+                                    || wParam == VK_RMENU) && !iMenuSysKey )
+                {
+                   iMenuSysKey = 1;
+                   /* mimic behaviour of XP, sending a WM_SYSCOMMAND when pressing <alt> */
+                   SendMessageW( top, WM_SYSCOMMAND, SC_KEYMENU, 0L );
+                }
+                else
+                   iMenuSysKey = 0;
+
+                iF10Key = 0;
+
                 if (wParam == VK_F4) /* Try to close the window */
                 {
-                    HWND top = GetAncestor(hWnd, GA_ROOT);
-                    if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
+                    if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
                     {
                         if (bUnicode)
                             PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
@@ -1259,41 +1416,72 @@ User32DefWindowProc(HWND hWnd,
                 }
                 else if (wParam == VK_SNAPSHOT)
                 {
-                    DefWndScreenshot(hWnd);
+                    HWND hwnd = hWnd;
+                    while (GetParent(hwnd) != NULL)
+                    {
+                        hwnd = GetParent(hwnd);
+                    }
+                    DefWndScreenshot(hwnd);
                 }
             }
+            else if( wParam == VK_F10 )
+                iF10Key = 1;
+            else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
+                SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
             break;
         }
 
-        case WM_SHOWWINDOW:
+        case WM_KEYUP:
+        case WM_SYSKEYUP:
         {
-            LONG Style;
-            INT Ret = 0;
-            
-            if (!lParam)
-                return 0;
-            Style = GetWindowLongW(hWnd, GWL_STYLE);
-//            if (!(Style & WS_POPUP))
-//                return 0;
-            if ((Style & WS_VISIBLE) && wParam)
-                return 0;
-            if (!(Style & WS_VISIBLE) && !wParam)
-                return 0;
-            if (!GetWindow(hWnd, GW_OWNER))
-                return 0;
-            Ret = NtUserCallTwoParam((DWORD) hWnd, (DWORD) wParam, TWOPARAM_ROUTINE_ROS_SHOWWINDOW);
-            if(Ret)
+           /* Press and release F10 or ALT */
+            if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
+                 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
+                SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
+            iMenuSysKey = iF10Key = 0;
+            break;
+        }
+
+        case WM_SYSCHAR:
+        {
+            iMenuSysKey = 0;
+            if (wParam == '\r' && IsIconic(hWnd))
+            {
+                PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
+                break;
+            }
+            if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
             {
-                if( Ret == -1) return 0;
-                return Ret;
+                if (wParam == '\t' || wParam == '\x1b') break;
+                if (wParam == ' ' && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
+                    SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
+                else
+                    SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
             }
-            ShowWindow(hWnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
+            else /* check for Ctrl-Esc */
+                if (wParam != '\x1b') MessageBeep(0);
+            break;
+        }
+
+        case WM_SHOWWINDOW:
+        {
+            if (lParam) // Call when it is necessary.
+               NtUserMessageCall( hWnd, Msg, wParam, lParam, 0, FNID_DEFWINDOWPROC, FALSE);
             break;
         }
 
+        case WM_CLIENTSHUTDOWN:
+        {
+            LRESULT lResult;
+            NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
+            return lResult;   
+        }
+
         case WM_CANCELMODE:
         {
+            iMenuSysKey = 0;
             /* FIXME: Check for a desktop. */
+            if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
             if (GetCapture() == hWnd)
             {
                 ReleaseCapture();
@@ -1306,12 +1494,11 @@ User32DefWindowProc(HWND hWnd,
             return (-1);
 /*
         case WM_DROPOBJECT:
-
-            break;
+            return DRAG_FILE;
 */
         case WM_QUERYDROPOBJECT:
         {
-            if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
+            if (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
             {
                 return(1);
             }
@@ -1323,7 +1510,7 @@ User32DefWindowProc(HWND hWnd,
             UINT Len;
             HICON hIcon;
 
-            hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
+            hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON);
             if (hIcon)
             {
                 return ((LRESULT)hIcon);
@@ -1342,21 +1529,16 @@ User32DefWindowProc(HWND hWnd,
 
         case WM_NOTIFYFORMAT:
         {
-            if (IsWindowUnicode(hWnd))
-            {
-                return(NFR_UNICODE);
-            }
-            else
-            {
-                return(NFR_ANSI);
-            }
+            if (lParam == NF_QUERY)
+                return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
+            break;
         }
 
         case WM_SETICON:
         {
            INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
-           HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
-           SetClassLongW(hWnd, Index, lParam);
+           HICON hOldIcon = (HICON)GetClassLongPtrW(hWnd, Index);
+           SetClassLongPtrW(hWnd, Index, lParam);
            SetWindowPos(hWnd, 0, 0, 0, 0, 0,
                       SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
                       SWP_NOACTIVATE | SWP_NOZORDER);
@@ -1366,7 +1548,7 @@ User32DefWindowProc(HWND hWnd,
         case WM_GETICON:
         {
             INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
-            return (GetClassLongW(hWnd, Index));
+            return (GetClassLongPtrW(hWnd, Index));
         }
 
         case WM_HELP:
@@ -1403,142 +1585,585 @@ User32DefWindowProc(HWND hWnd,
         {
             return (1);
         }
+
+        case WM_INPUTLANGCHANGEREQUEST:
+        {
+            HKL NewHkl;
+
+            if(wParam & INPUTLANGCHANGE_BACKWARD
+               && wParam & INPUTLANGCHANGE_FORWARD)
+            {
+                return FALSE;
+            }
+
+            //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
+
+            if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
+            else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
+            else NewHkl = (HKL) lParam;
+
+            NtUserActivateKeyboardLayout(NewHkl, 0);
+
+            return TRUE;
+        }
+
+        case WM_INPUTLANGCHANGE:
+        {
+            int count = 0;
+            HWND *win_array = WIN_ListChildren( hWnd );
+
+            if (!win_array)
+                break;
+            while (win_array[count])
+                SendMessageW( win_array[count++], WM_INPUTLANGCHANGE, wParam, lParam);
+            HeapFree(GetProcessHeap(),0,win_array);
+            break;
+        }
+
+        case WM_QUERYUISTATE:
+        {
+            LRESULT Ret = 0;
+            PWND Wnd = ValidateHwnd(hWnd);
+            if (Wnd != NULL)
+            {
+                if (Wnd->HideFocus)
+                    Ret |= UISF_HIDEFOCUS;
+                if (Wnd->HideAccel)
+                    Ret |= UISF_HIDEACCEL;
+            }
+            return Ret;
+        }
+
+        case WM_CHANGEUISTATE:
+        {
+            BOOL AlwaysShowCues = FALSE;
+            WORD Action = LOWORD(wParam);
+            WORD Flags = HIWORD(wParam);
+            PWND Wnd;
+
+            SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
+            if (AlwaysShowCues)
+                break;
+
+            Wnd= ValidateHwnd(hWnd);
+            if (!Wnd || lParam != 0)
+                break;
+
+            if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
+                break;
+
+            if (Flags & UISF_ACTIVE)
+            {
+                WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
+            }
+
+            if (Action == UIS_INITIALIZE)
+            {
+                PDESKTOPINFO Desk = GetThreadDesktopInfo();
+                if (Desk == NULL)
+                    break;
+
+                Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
+                Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
+
+                /* We need to update wParam in case we need to send out messages */
+                wParam = MAKEWPARAM(Action, Flags);
+            }
+
+            switch (Action)
+            {
+                case UIS_SET:
+                    /* See if we actually need to change something */
+                    if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
+                        break;
+                    if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
+                        break;
+
+                    /* Don't need to do anything... */
+                    return 0;
+
+                case UIS_CLEAR:
+                    /* See if we actually need to change something */
+                    if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
+                        break;
+                    if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
+                        break;
+
+                    /* Don't need to do anything... */
+                    return 0;
+
+                default:
+                    WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
+                    break;
+            }
+
+            if ((Wnd->style & WS_CHILD) && Wnd->spwndParent != NULL)
+            {
+                /* We're a child window and we need to pass this message down until
+                   we reach the root */
+                hWnd = UserHMGetHandle((PWND)DesktopPtrToUser(Wnd->spwndParent));
+            }
+            else
+            {
+                /* We're a top level window, we need to change the UI state */
+                Msg = WM_UPDATEUISTATE;
+            }
+
+            if (bUnicode)
+                return SendMessageW(hWnd, Msg, wParam, lParam);
+            else
+                return SendMessageA(hWnd, Msg, wParam, lParam);
+        }
+
+        case WM_UPDATEUISTATE:
+        {
+            BOOL Change = TRUE;
+            BOOL AlwaysShowCues = FALSE;
+            WORD Action = LOWORD(wParam);
+            WORD Flags = HIWORD(wParam);
+            PWND Wnd;
+
+            SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
+            if (AlwaysShowCues)
+                break;
+
+            Wnd = ValidateHwnd(hWnd);
+            if (!Wnd || lParam != 0)
+                break;
+
+            if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
+                break;
+
+            if (Flags & UISF_ACTIVE)
+            {
+                WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
+            }
+
+            if (Action == UIS_INITIALIZE)
+            {
+                PDESKTOPINFO Desk = GetThreadDesktopInfo();
+                if (Desk == NULL)
+                    break;
+
+                Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
+                Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
+
+                /* We need to update wParam for broadcasting the update */
+                wParam = MAKEWPARAM(Action, Flags);
+            }
+
+            switch (Action)
+            {
+                case UIS_SET:
+                    /* See if we actually need to change something */
+                    if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
+                        break;
+                    if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
+                        break;
+
+                    /* Don't need to do anything... */
+                    Change = FALSE;
+                    break;
+
+                case UIS_CLEAR:
+                    /* See if we actually need to change something */
+                    if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
+                        break;
+                    if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
+                        break;
+
+                    /* Don't need to do anything... */
+                    Change = FALSE;
+                    break;
+
+                default:
+                    WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
+                    return 0;
+            }
+
+            /* Pack the information and call win32k */
+            if (Change)
+            {
+                if (!NtUserCallTwoParam((DWORD)hWnd, (DWORD)Flags | ((DWORD)Action << 3), TWOPARAM_ROUTINE_ROS_UPDATEUISTATE))
+                    break;
+            }
+
+            /* Always broadcast the update to all children */
+            EnumChildWindows(hWnd,
+                             UserSendUiUpdateMsg,
+                             (LPARAM)wParam);
+
+            break;
+        }
+
     }
     return 0;
 }
 
 
-LRESULT STDCALL
+/*
+ * helpers for calling IMM32 (from Wine 10/22/2008)
+ *
+ * WM_IME_* messages are generated only by IMM32,
+ * so I assume imm32 is already LoadLibrary-ed.
+ */
+static HWND
+DefWndImmGetDefaultIMEWnd(HWND hwnd)
+{
+    HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
+    HWND (WINAPI *pFunc)(HWND);
+    HWND hwndRet = 0;
+
+    if (!hInstIMM)
+    {
+        ERR("cannot get IMM32 handle\n");
+        return 0;
+    }
+
+    pFunc = (void*) GetProcAddress(hInstIMM, "ImmGetDefaultIMEWnd");
+    if (pFunc != NULL)
+        hwndRet = (*pFunc)(hwnd);
+
+    return hwndRet;
+}
+
+
+static BOOL
+DefWndImmIsUIMessageA(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
+    BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
+    BOOL fRet = FALSE;
+
+    if (!hInstIMM)
+    {
+        ERR("cannot get IMM32 handle\n");
+        return FALSE;
+    }
+
+    pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageA");
+    if (pFunc != NULL)
+        fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
+
+    return fRet;
+}
+
+
+static BOOL
+DefWndImmIsUIMessageW(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
+    BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
+    BOOL fRet = FALSE;
+
+    if (!hInstIMM)
+    {
+        ERR("cannot get IMM32 handle\n");
+        return FALSE;
+    }
+
+    pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageW");
+    if (pFunc != NULL)
+        fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
+
+    return fRet;
+}
+
+
+LRESULT WINAPI
 DefWindowProcA(HWND hWnd,
               UINT Msg,
               WPARAM wParam,
               LPARAM lParam)
 {
+    LRESULT Result = 0;
+    PWND Wnd;
+
+    SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
     switch (Msg)
     {
         case WM_NCCREATE:
         {
-            return TRUE;
+            if (lParam)
+            {
+                LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
+                /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
+                 * may have child window IDs instead of window name */
+                if (HIWORD(cs->lpszName))
+                {
+                    DefSetText(hWnd, (PCWSTR)cs->lpszName, TRUE);
+                }
+                Result = 1;
+            }
+            break;
         }
 
         case WM_GETTEXTLENGTH:
         {
-            return (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
+            PWSTR buf;
+            ULONG len;
+
+            Wnd = ValidateHwnd(hWnd);
+            if (Wnd != NULL && Wnd->strName.Length != 0)
+            {
+                buf = DesktopPtrToUser(Wnd->strName.Buffer);
+                if (buf != NULL &&
+                    NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
+                                                         buf,
+                                                         Wnd->strName.Length)))
+                {
+                    Result = (LRESULT) len;
+                }
+            }
+            else Result = 0L;
+
+            break;
         }
 
         case WM_GETTEXT:
         {
-            LPWSTR Buffer;
-            LPSTR AnsiBuffer = (LPSTR)lParam;
-            INT Length;
+            PWSTR buf = NULL;
+            PSTR outbuf = (PSTR)lParam;
+            UINT copy;
 
-            Buffer = HeapAlloc(GetProcessHeap(), 0, wParam * sizeof(WCHAR));
-            if (!Buffer)
-                return FALSE;
-            Length = NtUserInternalGetWindowText(hWnd, Buffer, wParam);
-            if (Length > 0 && wParam > 0 &&
-                !WideCharToMultiByte(CP_ACP, 0, Buffer, -1,
-                AnsiBuffer, wParam, NULL, NULL))
+            Wnd = ValidateHwnd(hWnd);
+            if (Wnd != NULL && wParam != 0)
             {
-                AnsiBuffer[0] = '\0';
-            }
-
-            HeapFree(GetProcessHeap(), 0, Buffer);
+                if (Wnd->strName.Buffer != NULL)
+                    buf = DesktopPtrToUser(Wnd->strName.Buffer);
+                else
+                    outbuf[0] = L'\0';
 
-            return (LRESULT)Length;
+                if (buf != NULL)
+                {
+                    if (Wnd->strName.Length != 0)
+                    {
+                        copy = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
+                        Result = WideCharToMultiByte(CP_ACP,
+                                                     0,
+                                                     buf,
+                                                     copy,
+                                                     outbuf,
+                                                     wParam,
+                                                     NULL,
+                                                     NULL);
+                        outbuf[Result] = '\0';
+                    }
+                    else
+                        outbuf[0] = '\0';
+                }
+            }
+            break;
         }
 
         case WM_SETTEXT:
         {
-            ANSI_STRING AnsiString;
-            UNICODE_STRING UnicodeString;
+            DefSetText(hWnd, (PCWSTR)lParam, TRUE);
 
-            if(lParam)
-            {
-              RtlInitAnsiString(&AnsiString, (LPSTR)lParam);
-              RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
-              NtUserDefSetText(hWnd, &UnicodeString);
-              RtlFreeUnicodeString(&UnicodeString);
-            }
-            else
-              NtUserDefSetText(hWnd, NULL);
-
-            if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
+            if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
             {
                 DefWndNCPaint(hWnd, (HRGN)1, -1);
             }
-            return TRUE;
+
+            Result = 1;
+            break;
         }
 
-/*
-        FIXME: Implement these.
-        case WM_IME_CHAR:
         case WM_IME_KEYDOWN:
+        {
+            Result = PostMessageA(hWnd, WM_KEYDOWN, wParam, lParam);
+            break;
+        }
+
         case WM_IME_KEYUP:
+        {
+            Result = PostMessageA(hWnd, WM_KEYUP, wParam, lParam);
+            break;
+        }
+
+        case WM_IME_CHAR:
+        {
+            if (HIBYTE(wParam))
+                PostMessageA(hWnd, WM_CHAR, HIBYTE(wParam), lParam);
+            PostMessageA(hWnd, WM_CHAR, LOBYTE(wParam), lParam);
+            break;
+        }
+
         case WM_IME_STARTCOMPOSITION:
         case WM_IME_COMPOSITION:
         case WM_IME_ENDCOMPOSITION:
         case WM_IME_SELECT:
+        case WM_IME_NOTIFY:
+        {
+            HWND hwndIME;
+
+            hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
+            if (hwndIME)
+                Result = SendMessageA(hwndIME, Msg, wParam, lParam);
+            break;
+        }
+
         case WM_IME_SETCONTEXT:
-*/
+        {
+            HWND hwndIME;
+
+            hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
+            if (hwndIME)
+                Result = DefWndImmIsUIMessageA(hwndIME, Msg, wParam, lParam);
+            break;
+        }
+
+        /* fall through */
+        default:
+            Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
     }
 
-    return User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
+    SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
+    return Result;
 }
 
 
-LRESULT STDCALL
+LRESULT WINAPI
 DefWindowProcW(HWND hWnd,
               UINT Msg,
               WPARAM wParam,
               LPARAM lParam)
 {
+    LRESULT Result = 0;
+    PWND Wnd;
+
+    SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
     switch (Msg)
     {
         case WM_NCCREATE:
         {
-            return TRUE;
+            if (lParam)
+            {
+                LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
+                /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
+                 * may have child window IDs instead of window name */
+
+                if (HIWORD(cs->lpszName))
+                {
+                    DefSetText(hWnd, cs->lpszName, FALSE);
+                }
+                Result = 1;
+            }
+            break;
         }
 
         case WM_GETTEXTLENGTH:
         {
-            return (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
+            PWSTR buf;
+            ULONG len;
+
+            Wnd = ValidateHwnd(hWnd);
+            if (Wnd != NULL && Wnd->strName.Length != 0)
+            {
+                buf = DesktopPtrToUser(Wnd->strName.Buffer);
+                if (buf != NULL &&
+                    NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
+                                                         buf,
+                                                         Wnd->strName.Length)))
+                {
+                    Result = (LRESULT) (Wnd->strName.Length / sizeof(WCHAR));
+                }
+            }
+            else Result = 0L;
+
+            break;
         }
 
         case WM_GETTEXT:
         {
-            return (LRESULT)NtUserInternalGetWindowText(hWnd, (PWSTR)lParam, wParam);
+            PWSTR buf = NULL;
+            PWSTR outbuf = (PWSTR)lParam;
+
+            Wnd = ValidateHwnd(hWnd);
+            if (Wnd != NULL && wParam != 0)
+            {
+                if (Wnd->strName.Buffer != NULL)
+                    buf = DesktopPtrToUser(Wnd->strName.Buffer);
+                else
+                    outbuf[0] = L'\0';
+
+                if (buf != NULL)
+                {
+                    if (Wnd->strName.Length != 0)
+                    {
+                        Result = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
+                        RtlCopyMemory(outbuf,
+                                      buf,
+                                      Result * sizeof(WCHAR));
+                        outbuf[Result] = L'\0';
+                    }
+                    else
+                        outbuf[0] = L'\0';
+                }
+            }
+            break;
         }
 
         case WM_SETTEXT:
         {
-            UNICODE_STRING UnicodeString;
-
-            if(lParam)
-              RtlInitUnicodeString(&UnicodeString, (LPWSTR)lParam);
-
-            NtUserDefSetText(hWnd, (lParam ? &UnicodeString : NULL));
+            DefSetText(hWnd, (PCWSTR)lParam, FALSE);
 
-            if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
+            if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
             {
                 DefWndNCPaint(hWnd, (HRGN)1, -1);
             }
-            return (1);
+            Result = 1;
+            break;
         }
 
         case WM_IME_CHAR:
         {
-            SendMessageW(hWnd, WM_CHAR, wParam, lParam);
-            return (0);
+            PostMessageW(hWnd, WM_CHAR, wParam, lParam);
+            Result = 0;
+            break;
+        }
+
+        case WM_IME_KEYDOWN:
+        {
+            Result = PostMessageW(hWnd, WM_KEYDOWN, wParam, lParam);
+            break;
+        }
+
+        case WM_IME_KEYUP:
+        {
+            Result = PostMessageW(hWnd, WM_KEYUP, wParam, lParam);
+            break;
+        }
+
+        case WM_IME_STARTCOMPOSITION:
+        case WM_IME_COMPOSITION:
+        case WM_IME_ENDCOMPOSITION:
+        case WM_IME_SELECT:
+        case WM_IME_NOTIFY:
+        {
+            HWND hwndIME;
+
+            hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
+            if (hwndIME)
+                Result = SendMessageW(hwndIME, Msg, wParam, lParam);
+            break;
         }
 
         case WM_IME_SETCONTEXT:
         {
-            /* FIXME */
-            return (0);
+            HWND hwndIME;
+
+            hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
+            if (hwndIME)
+                Result = DefWndImmIsUIMessageW(hwndIME, Msg, wParam, lParam);
+            break;
         }
+
+        default:
+            Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
     }
+    SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
 
-    return User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
+    return Result;
 }