Author: tkreuzer
Date: Sat May 22 03:05:31 2010
New Revision: 47295
URL:
http://svn.reactos.org/svn/reactos?rev=47295&view=rev
Log:
[WIN32K / USER32]
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.
Modified:
trunk/reactos/dll/win32/user32/windows/window.c
trunk/reactos/include/reactos/win32k/ntuser.h
trunk/reactos/subsystems/win32/win32k/include/window.h
trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
trunk/reactos/subsystems/win32/win32k/ntuser/message.c
trunk/reactos/subsystems/win32/win32k/ntuser/painting.c
trunk/reactos/subsystems/win32/win32k/ntuser/window.c
Modified: trunk/reactos/dll/win32/user32/windows/window.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/w…
==============================================================================
--- trunk/reactos/dll/win32/user32/windows/window.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/user32/windows/window.c [iso-8859-1] Sat May 22 03:05:31 2010
@@ -137,6 +137,34 @@
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 @@
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 @@
if (IS_ATOM(lpClassName))
{
- RtlInitUnicodeString(&ClassName, NULL);
- ClassName.Buffer = (LPWSTR)lpClassName;
+ plstrClassName = (PVOID)lpClassName;
}
else
{
@@ -180,26 +208,49 @@
RtlInitUnicodeString(&ClassName, (PCWSTR)lpClassName);
else
{
- if (!RtlCreateUnicodeStringFromAsciiz(&(ClassName), (PCSZ)lpClassName))
+ if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, (PCSZ)lpClassName))
{
SetLastError(ERROR_OUTOFMEMORY);
return (HWND)0;
}
}
- }
-
- if (Unicode)
- RtlInitUnicodeString(&WindowName, (PCWSTR)lpWindowName);
- else
- {
- if (!RtlCreateUnicodeStringFromAsciiz(&WindowName, (PCSZ)lpWindowName))
- {
- if (!IS_ATOM(lpClassName))
- {
- RtlFreeUnicodeString(&ClassName);
- }
+
+ /* Copy it to a LARGE_STRING */
+ lstrClassName.Buffer = ClassName.Buffer;
+ lstrClassName.Length = ClassName.Length;
+ lstrClassName.MaximumLength = ClassName.MaximumLength;
+ plstrClassName = &lstrClassName;
+ }
+
+ /* Initialize a LARGE_STRING */
+ RtlInitLargeString(&WindowName, lpWindowName, Unicode);
+
+ // HACK: The current implementation expects the Window name to be UNICODE
+ if (!Unicode)
+ {
+ 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)
+ {
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 @@
}
}
+ if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR;
+
Handle = NtUserCreateWindowEx(dwExStyle,
- &ClassName,
+ plstrClassName,
+ NULL,
&WindowName,
dwStyle,
x,
@@ -235,23 +289,23 @@
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;
}
Modified: trunk/reactos/include/reactos/win32k/ntuser.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntu…
==============================================================================
--- trunk/reactos/include/reactos/win32k/ntuser.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/win32k/ntuser.h [iso-8859-1] Sat May 22 03:05:31 2010
@@ -514,7 +514,7 @@
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;
@@ -1472,28 +1472,9 @@
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 @@
LPVOID lpParam,
DWORD dwFlags,
PVOID acbiBuffer);
-#endif
HWINSTA
NTAPI
Modified: trunk/reactos/subsystems/win32/win32k/include/window.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/window.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/window.h [iso-8859-1] Sat May 22
03:05:31 2010
@@ -155,7 +155,7 @@
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 */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c [iso-8859-1] Sat May 22
03:05:31 2010
@@ -882,7 +882,8 @@
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);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] Sat May 22
03:05:31 2010
@@ -171,7 +171,7 @@
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 @@
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))
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/painting.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/painting.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/painting.c [iso-8859-1] Sat May 22
03:05:31 2010
@@ -1896,7 +1896,13 @@
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,
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] Sat May 22 03:05:31
2010
@@ -1660,7 +1660,7 @@
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 @@
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 Status;
- UNICODE_STRING WindowName;
- UNICODE_STRING ClassName;
- HWND NewWindow = NULL;
- PWND pNewWindow;
- DECLARE_RETURN(HWND);
-
- DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth,
nHeight);
- UserEnterExclusive();
-
- /* 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);
- }
-
- /* 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);
- }
-
- pNewWindow = co_IntCreateWindowEx( dwExStyle,
- &ClassName,
- &WindowName,
- dwStyle,
- x,
- y,
- nWidth,
- nHeight,
- hWndParent,
- hMenu,
- hInstance,
- lpParam,
- dwShowMode,
- bUnicodeWindow);
-
- if (pNewWindow) NewWindow = UserHMGetHandle(pNewWindow);
-
- if (WindowName.Buffer)
- {
- ExFreePoolWithTag(WindowName.Buffer, TAG_STRING);
- }
- if (! IS_ATOM(ClassName.Buffer))
- {
- ExFreePoolWithTag(ClassName.Buffer, TAG_STRING);
- }
-
- RETURN( NewWindow);
-
-CLEANUP:
- DPRINT("Leave NtUserCreateWindowEx, ret=%i\n",_ret_);
+NTSTATUS
+NTAPI
+ProbeAndCaptureLargeString(
+ OUT PLARGE_STRING plstrSafe,
+ IN PLARGE_STRING plstrUnsafe)
+{
+ LARGE_STRING lstrTemp;
+ PVOID pvBuffer = NULL;
+
+ _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
+
+ 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
+ }
+
+ /* Set the output string */
+ plstrSafe->Buffer = pvBuffer;
+ plstrSafe->Length = lstrTemp.Length;
+ plstrSafe->MaximumLength = lstrTemp.Length;
+
+ return STATUS_SUCCESS;
+}
+
+/**
+ * \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;
+
+ DPRINT("Enter NtUserCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, nWidth,
nHeight);
+ UserEnterExclusive();
+
+ lstrWindowName.Buffer = NULL;
+ lstrClassName.Buffer = NULL;
+
+ /* 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 @@
BOOL CheckWindowName;
HWND *List, *phWnd;
HWND Ret = NULL;
+ UNICODE_STRING CurrentWindowName;
ASSERT(Parent);
@@ -2879,13 +2940,20 @@
/* 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 @@
/* search children */
while(*phWnd)
{
+ UNICODE_STRING ustr;
+
if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
{
continue;
@@ -3050,8 +3120,12 @@
/* 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;