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,
LPVOID lpParam,
BOOL Unicode)
{
- UNICODE_STRING WindowName;
+ LARGE_STRING WindowName;
+ LARGE_STRING lstrClassName, *plstrClassName;
UNICODE_STRING ClassName;
WNDCLASSEXA wceA;
WNDCLASSEXW wceW;
if (IS_ATOM(lpClassName))
{
- RtlInitUnicodeString(&ClassName, NULL);
- ClassName.Buffer = (LPWSTR)lpClassName;
+ plstrClassName = (PVOID)lpClassName;
}
else
{
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;
}
}
}
}
+ if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR;
+
Handle = NtUserCreateWindowEx(dwExStyle,
- &ClassName,
+ plstrClassName,
+ NULL,
&WindowName,
dwStyle,
x,
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;
}
PWND APIENTRY
co_IntCreateWindowEx(DWORD dwExStyle,
PUNICODE_STRING ClassName,
- PUNICODE_STRING WindowName,
+ PLARGE_STRING WindowName,
DWORD dwStyle,
LONG x,
LONG y,
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;
}
/*
BOOL CheckWindowName;
HWND *List, *phWnd;
HWND Ret = NULL;
+ UNICODE_STRING CurrentWindowName;
ASSERT(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);
}
/* search children */
while(*phWnd)
{
+ UNICODE_STRING ustr;
+
if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
{
continue;
/* 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;