From: Timo Kreuzer Date: Sat, 22 May 2010 01:05:31 +0000 (+0000) Subject: [WIN32K / USER32] X-Git-Tag: backups/header-work@57446~16^2~4 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=709fe1efeffe825d3a9c3dda2437a005fe515ccc [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. svn path=/trunk/; revision=47295 --- diff --git a/reactos/dll/win32/user32/windows/window.c b/reactos/dll/win32/user32/windows/window.c index 2aa01a9941d..bd4541c2cd2 100644 --- a/reactos/dll/win32/user32/windows/window.c +++ b/reactos/dll/win32/user32/windows/window.c @@ -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; } diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index 53a8f6a3311..0d6d7811db7 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -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 diff --git a/reactos/subsystems/win32/win32k/include/window.h b/reactos/subsystems/win32/win32k/include/window.h index 16098e456b1..90143244458 100644 --- a/reactos/subsystems/win32/win32k/include/window.h +++ b/reactos/subsystems/win32/win32k/include/window.h @@ -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 */ diff --git a/reactos/subsystems/win32/win32k/ntuser/desktop.c b/reactos/subsystems/win32/win32k/ntuser/desktop.c index df04a4f5313..1c972f95075 100644 --- a/reactos/subsystems/win32/win32k/ntuser/desktop.c +++ b/reactos/subsystems/win32/win32k/ntuser/desktop.c @@ -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); diff --git a/reactos/subsystems/win32/win32k/ntuser/message.c b/reactos/subsystems/win32/win32k/ntuser/message.c index 12744d3a14f..b626b881db4 100644 --- a/reactos/subsystems/win32/win32k/ntuser/message.c +++ b/reactos/subsystems/win32/win32k/ntuser/message.c @@ -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)) diff --git a/reactos/subsystems/win32/win32k/ntuser/painting.c b/reactos/subsystems/win32/win32k/ntuser/painting.c index ce612a5076a..0e042410757 100644 --- a/reactos/subsystems/win32/win32k/ntuser/painting.c +++ b/reactos/subsystems/win32/win32k/ntuser/painting.c @@ -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, diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index 965b007b8b9..e3bd9bd6235 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -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;