[WIN32K / USER32]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 22 May 2010 01:05:31 +0000 (01:05 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 22 May 2010 01:05:31 +0000 (01:05 +0000)
Convert the window text string from UNICODE_STRING to LARGE_STRING and fix NtUserCreateWindowEx parameters. We currently still pass UNICODE only LARGE_STRINGs, as the rest of the code in win32k expects this.
Fixes display of large text windows, like the winzip license.
See issue #2900 for more details.

svn path=/trunk/; revision=47295

reactos/dll/win32/user32/windows/window.c
reactos/include/reactos/win32k/ntuser.h
reactos/subsystems/win32/win32k/include/window.h
reactos/subsystems/win32/win32k/ntuser/desktop.c
reactos/subsystems/win32/win32k/ntuser/message.c
reactos/subsystems/win32/win32k/ntuser/painting.c
reactos/subsystems/win32/win32k/ntuser/window.c

index 2aa01a9..bd4541c 100644 (file)
@@ -137,6 +137,34 @@ CloseWindow(HWND hWnd)
     return (BOOL)(hWnd);
 }
 
+VOID
+FORCEINLINE
+RtlInitLargeString(
+    OUT PLARGE_STRING plstr,
+    LPCVOID psz,
+    BOOL bUnicode)
+{
+    if(bUnicode)
+    {
+        RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)plstr, (PWSTR)psz, 0);
+    }
+    else
+    {
+        RtlInitLargeAnsiString((PLARGE_ANSI_STRING)plstr, (PSTR)psz, 0);
+    }
+}
+
+VOID
+NTAPI
+RtlFreeLargeString(
+    IN PLARGE_STRING LargeString)
+{
+    if (LargeString->Buffer)
+    {
+        RtlFreeHeap(GetProcessHeap(), 0, LargeString->Buffer);
+        RtlZeroMemory(LargeString, sizeof(LARGE_STRING));
+    }
+}
 
 HWND WINAPI
 User32CreateWindowEx(DWORD dwExStyle,
@@ -153,7 +181,8 @@ User32CreateWindowEx(DWORD dwExStyle,
                      LPVOID lpParam,
                      BOOL Unicode)
 {
-    UNICODE_STRING WindowName;
+    LARGE_STRING WindowName;
+    LARGE_STRING lstrClassName, *plstrClassName;
     UNICODE_STRING ClassName;
     WNDCLASSEXA wceA;
     WNDCLASSEXW wceW;
@@ -171,8 +200,7 @@ User32CreateWindowEx(DWORD dwExStyle,
 
     if (IS_ATOM(lpClassName))
     {
-        RtlInitUnicodeString(&ClassName, NULL);
-        ClassName.Buffer = (LPWSTR)lpClassName;
+        plstrClassName = (PVOID)lpClassName;
     }
     else
     {
@@ -180,26 +208,49 @@ User32CreateWindowEx(DWORD dwExStyle,
             RtlInitUnicodeString(&ClassName, (PCWSTR)lpClassName);
         else
         {
-            if (!RtlCreateUnicodeStringFromAsciiz(&(ClassName), (PCSZ)lpClassName))
+            if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, (PCSZ)lpClassName))
             {
                 SetLastError(ERROR_OUTOFMEMORY);
                 return (HWND)0;
             }
         }
+        
+        /* Copy it to a LARGE_STRING */
+        lstrClassName.Buffer = ClassName.Buffer;
+        lstrClassName.Length = ClassName.Length;
+        lstrClassName.MaximumLength = ClassName.MaximumLength;
+        plstrClassName = &lstrClassName;
     }
 
-    if (Unicode)
-        RtlInitUnicodeString(&WindowName, (PCWSTR)lpWindowName);
-    else
+    /* Initialize a LARGE_STRING */
+    RtlInitLargeString(&WindowName, lpWindowName, Unicode);
+
+    // HACK: The current implementation expects the Window name to be UNICODE
+    if (!Unicode)
     {
-        if (!RtlCreateUnicodeStringFromAsciiz(&WindowName, (PCSZ)lpWindowName))
+        NTSTATUS Status;
+        PSTR AnsiBuffer = WindowName.Buffer;
+        ULONG AnsiLength = WindowName.Length;
+        
+        WindowName.Length = 0;
+        WindowName.MaximumLength = AnsiLength * sizeof(WCHAR);
+        WindowName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+                                            0,
+                                            WindowName.MaximumLength);
+        if (!WindowName.Buffer)
         {
-            if (!IS_ATOM(lpClassName))
-            {
-                RtlFreeUnicodeString(&ClassName);
-            }
             SetLastError(ERROR_OUTOFMEMORY);
-            return (HWND)0;
+            goto cleanup;
+        }
+
+        Status = RtlMultiByteToUnicodeN(WindowName.Buffer,
+                                        WindowName.MaximumLength,
+                                        &WindowName.Length,
+                                        AnsiBuffer,
+                                        AnsiLength);
+        if (!NT_SUCCESS(Status))
+        {
+            goto cleanup;
         }
     }
 
@@ -223,8 +274,11 @@ User32CreateWindowEx(DWORD dwExStyle,
         }
     }
 
+    if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR;
+
     Handle = NtUserCreateWindowEx(dwExStyle,
-                                  &ClassName,
+                                  plstrClassName,
+                                  NULL,
                                   &WindowName,
                                   dwStyle,
                                   x,
@@ -235,23 +289,23 @@ User32CreateWindowEx(DWORD dwExStyle,
                                   hMenu,
                                   hInstance,
                                   lpParam,
-                                  SW_SHOW,
-                                  Unicode,
-                                  0);
+                                  0,
+                                  NULL);
 
 #if 0
     DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle);
 #endif
-
+cleanup:
     if(!Unicode)
     {
-        RtlFreeUnicodeString(&WindowName);
-
         if (!IS_ATOM(lpClassName))
         {
             RtlFreeUnicodeString(&ClassName);
         }
+        
+        RtlFreeLargeString(&WindowName);
     }
+
     return Handle;
 }
 
index 53a8f6a..0d6d781 100644 (file)
@@ -514,7 +514,7 @@ typedef struct _WND
     HRGN hrgnClip;
     HRGN hrgnNewFrame;
     /* Window name. */
-    UNICODE_STRING strName;
+    LARGE_UNICODE_STRING strName;
     /* Size of the extra data associated with the window. */
     ULONG cbwndExtra;
     HWND hWndLastActive;
@@ -1469,31 +1469,12 @@ NtUserCreateLocalMemHandle(
   DWORD Unknown2,
   DWORD Unknown3);
 
-HWND
-NTAPI
-NtUserCreateWindowEx(
-  DWORD dwExStyle,
-  PUNICODE_STRING lpClassName,
-  PUNICODE_STRING lpWindowName,
-  DWORD dwStyle,
-  LONG x,
-  LONG y,
-  LONG nWidth,
-  LONG nHeight,
-  HWND hWndParent,
-  HMENU hMenu,
-  HINSTANCE hInstance,
-  LPVOID lpParam,
-  DWORD dwShowMode,
-  BOOL bUnicodeWindow,
-  DWORD dwUnknown);
-#if 0
 HWND
 NTAPI
 NtUserCreateWindowEx(
   DWORD dwExStyle, // |= 0x80000000 == Ansi used to set WNDS_ANSICREATOR
   PLARGE_STRING plstrClassName,
-  PLARGE_STRING plstrClsVesrion,
+  PLARGE_STRING plstrClsVersion,
   PLARGE_STRING plstrWindowName,
   DWORD dwStyle,
   int x,
@@ -1506,7 +1487,6 @@ NtUserCreateWindowEx(
   LPVOID lpParam,
   DWORD dwFlags,
   PVOID acbiBuffer);
-#endif
 
 HWINSTA
 NTAPI
index 16098e4..9014324 100644 (file)
@@ -155,7 +155,7 @@ IntDefWindowProc( PWINDOW_OBJECT Window, UINT Msg, WPARAM wParam, LPARAM lParam,
 
 VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG);
 
-PWND APIENTRY co_IntCreateWindowEx(DWORD,PUNICODE_STRING,PUNICODE_STRING,DWORD,LONG,LONG,LONG,LONG,HWND,HMENU,HINSTANCE,LPVOID,DWORD,BOOL);
+PWND APIENTRY co_IntCreateWindowEx(DWORD,PUNICODE_STRING,PLARGE_STRING,DWORD,LONG,LONG,LONG,LONG,HWND,HMENU,HINSTANCE,LPVOID,DWORD,BOOL);
 WNDPROC FASTCALL IntGetWindowProc(PWND,BOOL);
 
 /* EOF */
index df04a4f..1c972f9 100644 (file)
@@ -882,7 +882,8 @@ NtUserCreateDesktop(
    ULONG_PTR HeapSize = 4 * 1024 * 1024; /* FIXME */
    HWINSTA hWindowStation = NULL ;
    PUNICODE_STRING lpszDesktopName = NULL;
-   UNICODE_STRING ClassName, WindowName, MenuName;
+   UNICODE_STRING ClassName, MenuName;
+   LARGE_STRING WindowName;
    PWND pWnd = NULL;
    DECLARE_RETURN(HDESK);
 
index 12744d3..b626b88 100644 (file)
@@ -171,7 +171,7 @@ PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Non
    NCCALCSIZE_PARAMS *PackedNcCalcsize;
    CREATESTRUCTW *UnpackedCs;
    CREATESTRUCTW *PackedCs;
-   PUNICODE_STRING WindowName;
+   PLARGE_STRING WindowName;
    PUNICODE_STRING ClassName;
    POOL_TYPE PoolType;
    UINT Size;
@@ -205,7 +205,7 @@ PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Non
    else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
    {
       UnpackedCs = (CREATESTRUCTW *) lParam;
-      WindowName = (PUNICODE_STRING) UnpackedCs->lpszName;
+      WindowName = (PLARGE_STRING) UnpackedCs->lpszName;
       ClassName = (PUNICODE_STRING) UnpackedCs->lpszClass;
       Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
       if (IS_ATOM(ClassName->Buffer))
index ce612a5..0e04241 100644 (file)
@@ -1896,7 +1896,13 @@ BOOL UserDrawCaption(
       if (str)
          UserDrawCaptionText(hMemDc, str, &r, uFlags);
       else if (pWnd != NULL)
-         UserDrawCaptionText(hMemDc, &pWnd->Wnd->strName, &r, uFlags);
+      {
+         UNICODE_STRING ustr;
+         ustr.Buffer = pWnd->Wnd->strName.Buffer;
+         ustr.Length = pWnd->Wnd->strName.Length;
+         ustr.MaximumLength = pWnd->Wnd->strName.MaximumLength;
+         UserDrawCaptionText(hMemDc, &ustr, &r, uFlags);
+      }
    }
 
    if(!NtGdiBitBlt(hDc, lpRc->left, lpRc->top,
index 965b007..e3bd9bd 100644 (file)
@@ -1660,7 +1660,7 @@ IntCalcDefPosSize(PWINDOW_OBJECT Parent, RECTL *rc, BOOL IncPos)
 PWND APIENTRY
 co_IntCreateWindowEx(DWORD dwExStyle,
                      PUNICODE_STRING ClassName,
-                     PUNICODE_STRING WindowName,
+                     PLARGE_STRING WindowName,
                      DWORD dwStyle,
                      LONG x,
                      LONG y,
@@ -2485,106 +2485,166 @@ CLEANUP:
    END_CLEANUP;
 }
 
-HWND APIENTRY
-NtUserCreateWindowEx(DWORD dwExStyle,
-                     PUNICODE_STRING UnsafeClassName,
-                     PUNICODE_STRING UnsafeWindowName,
-                     DWORD dwStyle,
-                     LONG x,
-                     LONG y,
-                     LONG nWidth,
-                     LONG nHeight,
-                     HWND hWndParent,
-                     HMENU hMenu,
-                     HINSTANCE hInstance,
-                     LPVOID lpParam,
-                     DWORD dwShowMode,
-                     BOOL bUnicodeWindow,
-                     DWORD dwUnknown)
+NTSTATUS
+NTAPI
+ProbeAndCaptureLargeString(
+    OUT PLARGE_STRING plstrSafe,
+    IN PLARGE_STRING plstrUnsafe)
 {
-   NTSTATUS Status;
-   UNICODE_STRING WindowName;
-   UNICODE_STRING ClassName;
-   HWND NewWindow = NULL;
-   PWND pNewWindow;
-   DECLARE_RETURN(HWND);
+    LARGE_STRING lstrTemp;
+    PVOID pvBuffer = NULL;
 
-   DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
-   UserEnterExclusive();
+    _SEH2_TRY
+    {
+        /* Probe and copy the string */
+        ProbeForRead(plstrUnsafe, sizeof(LARGE_STRING), sizeof(ULONG));
+        lstrTemp = *plstrUnsafe;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Fail */
+        _SEH2_YIELD(return _SEH2_GetExceptionCode();)
+    }
+    _SEH2_END
 
-   /* Get the class name (string or atom) */
-   Status = MmCopyFromCaller(&ClassName, UnsafeClassName, sizeof(UNICODE_STRING));
-   if (! NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN( NULL);
-   }
-   if (ClassName.Length != 0)
-   {
-      Status = IntSafeCopyUnicodeStringTerminateNULL(&ClassName, UnsafeClassName);
-      if (! NT_SUCCESS(Status))
-      {
-         SetLastNtError(Status);
-         RETURN( NULL);
-      }
-   }
-   else if (! IS_ATOM(ClassName.Buffer))
-   {
-       SetLastWin32Error(ERROR_INVALID_PARAMETER);
-       RETURN(NULL);
-   }
+    if (lstrTemp.Length != 0)
+    {
+        /* Allocate a buffer from paged pool */
+        pvBuffer = ExAllocatePoolWithTag(PagedPool, lstrTemp.Length, TAG_STRING);
+        if (!pvBuffer)
+        {
+            return STATUS_NO_MEMORY;
+        }
+
+        _SEH2_TRY
+        {
+            /* Probe and copy the buffer */
+            ProbeForRead(lstrTemp.Buffer, lstrTemp.Length, sizeof(WCHAR));
+            RtlCopyMemory(pvBuffer, lstrTemp.Buffer, lstrTemp.Length);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Cleanup and fail */
+            ExFreePool(pvBuffer);
+            _SEH2_YIELD(return _SEH2_GetExceptionCode();)
+        }
+        _SEH2_END
+    }
 
-   /* safely copy the window name */
-   if (NULL != UnsafeWindowName)
-   {
-      Status = IntSafeCopyUnicodeString(&WindowName, UnsafeWindowName);
-      if (! NT_SUCCESS(Status))
-      {
-         if (! IS_ATOM(ClassName.Buffer))
-         {
-            ExFreePoolWithTag(ClassName.Buffer, TAG_STRING);
-         }
-         SetLastNtError(Status);
-         RETURN( NULL);
-      }
-   }
-   else
-   {
-      RtlInitUnicodeString(&WindowName, NULL);
-   }
+    /* Set the output string */
+    plstrSafe->Buffer = pvBuffer;
+    plstrSafe->Length = lstrTemp.Length;
+    plstrSafe->MaximumLength = lstrTemp.Length;
 
-   pNewWindow = co_IntCreateWindowEx( dwExStyle,
-                                     &ClassName,
-                                     &WindowName,
-                                      dwStyle,
-                                      x,
-                                      y,
-                                      nWidth,
-                                      nHeight,
-                                      hWndParent,
-                                      hMenu,
-                                      hInstance,
-                                      lpParam,
-                                      dwShowMode,
-                                      bUnicodeWindow);
+    return STATUS_SUCCESS;
+}
 
-   if (pNewWindow) NewWindow = UserHMGetHandle(pNewWindow);
+/**
+ * \todo Allow passing plstrClassName as ANSI.
+ */
+HWND
+NTAPI
+NtUserCreateWindowEx(
+    DWORD dwExStyle,
+    PLARGE_STRING plstrClassName,
+    PLARGE_STRING plstrClsVersion,
+    PLARGE_STRING plstrWindowName,
+    DWORD dwStyle,
+    int x,
+    int y,
+    int nWidth,
+    int nHeight,
+    HWND hWndParent,
+    HMENU hMenu,
+    HINSTANCE hInstance,
+    LPVOID lpParam,
+    DWORD dwFlags,
+    PVOID acbiBuffer)
+{
+    NTSTATUS Status;
+    LARGE_STRING lstrWindowName;
+    LARGE_STRING lstrClassName;
+    UNICODE_STRING ustrClassName;
+    HWND hwnd = NULL;
+    PWND pwnd;
 
-   if (WindowName.Buffer)
-   {
-      ExFreePoolWithTag(WindowName.Buffer, TAG_STRING);
-   }
-   if (! IS_ATOM(ClassName.Buffer))
-   {
-      ExFreePoolWithTag(ClassName.Buffer, TAG_STRING);
-   }
+    DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth, nHeight);
+    UserEnterExclusive();
 
-   RETURN( NewWindow);
+    lstrWindowName.Buffer = NULL;
+    lstrClassName.Buffer = NULL;
 
-CLEANUP:
-   DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_);
+    /* Check if we got a Window name */
+    if (plstrWindowName)
+    {
+        /* Copy the string to kernel mode */
+        Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            goto leave;
+        }
+        plstrWindowName = &lstrWindowName;
+    }
+
+    /* Check if the class is an atom */
+    if (IS_ATOM(plstrClassName))
+    {
+        /* It is, pass the atom in the UNICODE_STRING */
+        ustrClassName.Buffer = (PVOID)plstrClassName;
+        ustrClassName.Length = 0;
+        ustrClassName.MaximumLength = 0;
+    }
+    else
+    {
+        /* It's not, capture the class name */
+        Status = ProbeAndCaptureLargeString(&lstrClassName, plstrClassName);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Set last error, cleanup and return */
+            SetLastNtError(Status);
+            goto cleanup;
+        }
+
+        /* We pass it on as a UNICODE_STRING */
+        ustrClassName.Buffer = lstrClassName.Buffer;
+        ustrClassName.Length = lstrClassName.Length;
+        ustrClassName.MaximumLength = lstrClassName.MaximumLength;
+    }
+
+    /* Call the internal function */
+    pwnd = co_IntCreateWindowEx(dwExStyle,
+                                &ustrClassName,
+                                plstrWindowName,
+                                dwStyle,
+                                x,
+                                y,
+                                nWidth,
+                                nHeight,
+                                hWndParent,
+                                hMenu,
+                                hInstance,
+                                lpParam,
+                                SW_SHOW,
+                                !(dwExStyle & WS_EX_SETANSICREATOR));
+
+    hwnd = pwnd ? UserHMGetHandle(pwnd) : NULL;
+
+cleanup:
+    if (lstrWindowName.Buffer)
+    {
+        ExFreePoolWithTag(lstrWindowName.Buffer, TAG_STRING);
+    }
+    if (lstrClassName.Buffer)
+    {
+        ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
+    }
+
+leave:
+   DPRINT("Leave NtUserCreateWindowEx, hwnd=%i\n", hwnd);
    UserLeave();
-   END_CLEANUP;
+
+   return hwnd;
 }
 
 /*
@@ -2852,6 +2912,7 @@ IntFindWindow(PWINDOW_OBJECT Parent,
    BOOL CheckWindowName;
    HWND *List, *phWnd;
    HWND Ret = NULL;
+   UNICODE_STRING CurrentWindowName;
 
    ASSERT(Parent);
 
@@ -2879,13 +2940,20 @@ IntFindWindow(PWINDOW_OBJECT 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((!CheckWindowName || !RtlCompareUnicodeString(WindowName, &(Child->Wnd->strName), TRUE)) &&
-               (!ClassAtom || Child->Wnd->pcls->atomClassName == ClassAtom))
+         if (!ClassAtom || Child->Wnd->pcls->atomClassName == ClassAtom)
          {
-            Ret = Child->hSelf;
-            break;
+             // HACK: use UNICODE_STRING instead of LARGE_STRING
+             CurrentWindowName.Buffer = Child->Wnd->strName.Buffer;
+             CurrentWindowName.Length = Child->Wnd->strName.Length;
+             CurrentWindowName.MaximumLength = Child->Wnd->strName.MaximumLength;
+             if(!CheckWindowName || 
+                (Child->Wnd->strName.Length < 0xFFFF &&
+                 !RtlCompareUnicodeString(WindowName, &CurrentWindowName, TRUE)))
+             {
+                Ret = Child->hSelf;
+                break;
+             }
          }
-
       }
       ExFreePool(List);
    }
@@ -3042,6 +3110,8 @@ NtUserFindWindowEx(HWND hwndParent,
              /* search children */
              while(*phWnd)
              {
+                 UNICODE_STRING ustr;
+
                 if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
                 {
                    continue;
@@ -3050,8 +3120,12 @@ NtUserFindWindowEx(HWND hwndParent,
                 /* 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 */
-                WindowMatches = !CheckWindowName || !RtlCompareUnicodeString(
-                                   &WindowName, &TopLevelWindow->Wnd->strName, TRUE);
+                ustr.Buffer = TopLevelWindow->Wnd->strName.Buffer;
+                ustr.Length = TopLevelWindow->Wnd->strName.Length;
+                ustr.MaximumLength = TopLevelWindow->Wnd->strName.MaximumLength;
+                WindowMatches = !CheckWindowName || 
+                                (TopLevelWindow->Wnd->strName.Length < 0xFFFF && 
+                                 !RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
                 ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
                                ClassAtom == TopLevelWindow->Wnd->pcls->atomClassName;