Optimize GetWindowText(Length)A/W and WM_GETTEXT(LENGTH)

svn path=/trunk/; revision=30490
This commit is contained in:
Thomas Bluemel 2007-11-16 02:37:14 +00:00
parent 99767a3b59
commit fdb8bd5a53
11 changed files with 318 additions and 151 deletions

View file

@ -1602,6 +1602,7 @@ DefWindowProcA(HWND hWnd,
LPARAM lParam) LPARAM lParam)
{ {
LRESULT Result = 0; LRESULT Result = 0;
PWINDOW Wnd;
SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam); SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
switch (Msg) switch (Msg)
@ -1630,33 +1631,57 @@ DefWindowProcA(HWND hWnd,
case WM_GETTEXTLENGTH: case WM_GETTEXTLENGTH:
{ {
Result = (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0); PWSTR buf;
ULONG len;
Wnd = ValidateHwnd(hWnd);
if (Wnd != NULL && Wnd->WindowName.Length != 0)
{
buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
if (buf != NULL &&
NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
buf,
Wnd->WindowName.Length)))
{
Result = (LRESULT)len;
}
}
break; break;
} }
case WM_GETTEXT: case WM_GETTEXT:
{ {
LPWSTR Buffer; PWSTR buf = NULL;
LPSTR AnsiBuffer = (LPSTR)lParam; PSTR outbuf = (PSTR)lParam;
INT Length; UINT copy;
Buffer = HeapAlloc(GetProcessHeap(), 0, wParam * sizeof(WCHAR)); Wnd = ValidateHwnd(hWnd);
if (!Buffer) if (Wnd != NULL && wParam != 0)
{ {
Result = 0; if (Wnd->WindowName.Buffer != NULL)
break; buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
} else
Length = NtUserInternalGetWindowText(hWnd, Buffer, wParam); outbuf[0] = L'\0';
if (Length > 0 && wParam > 0 &&
!WideCharToMultiByte(CP_ACP, 0, Buffer, -1,
AnsiBuffer, wParam, NULL, NULL))
{
AnsiBuffer[0] = '\0';
}
HeapFree(GetProcessHeap(), 0, Buffer); if (buf != NULL)
{
Result = (LRESULT)Length; if (Wnd->WindowName.Length != 0)
{
copy = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
Result = WideCharToMultiByte(CP_ACP,
0,
buf,
copy,
outbuf,
wParam,
NULL,
NULL);
outbuf[Result] = '\0';
}
else
outbuf[0] = '\0';
}
}
break; break;
} }
@ -1711,6 +1736,7 @@ DefWindowProcW(HWND hWnd,
LPARAM lParam) LPARAM lParam)
{ {
LRESULT Result = 0; LRESULT Result = 0;
PWINDOW Wnd;
SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam); SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
switch (Msg) switch (Msg)
@ -1732,13 +1758,51 @@ DefWindowProcW(HWND hWnd,
case WM_GETTEXTLENGTH: case WM_GETTEXTLENGTH:
{ {
Result = (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0); PWSTR buf;
ULONG len;
Wnd = ValidateHwnd(hWnd);
if (Wnd != NULL && Wnd->WindowName.Length != 0)
{
buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
if (buf != NULL &&
NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
buf,
Wnd->WindowName.Length)))
{
Result = (LRESULT)len;
}
}
break; break;
} }
case WM_GETTEXT: case WM_GETTEXT:
{ {
Result = (LRESULT)NtUserInternalGetWindowText(hWnd, (PWSTR)lParam, wParam); PWSTR buf = NULL;
PWSTR outbuf = (PWSTR)lParam;
Wnd = ValidateHwnd(hWnd);
if (Wnd != NULL && wParam != 0)
{
if (Wnd->WindowName.Buffer != NULL)
buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
else
outbuf[0] = L'\0';
if (buf != NULL)
{
if (Wnd->WindowName.Length != 0)
{
Result = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
RtlCopyMemory(outbuf,
buf,
Result * sizeof(WCHAR));
outbuf[Result] = L'\0';
}
else
outbuf[0] = L'\0';
}
}
break; break;
} }

View file

@ -1035,31 +1035,50 @@ GetWindowRect(HWND hWnd,
int STDCALL int STDCALL
GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount) GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
{ {
DWORD ProcessId; PWINDOW Wnd;
PCWSTR Buffer;
if (lpString == NULL) if (lpString == NULL)
return 0; return 0;
if (!NtUserGetWindowThreadProcessId(hWnd, &ProcessId)) Wnd = ValidateHwnd(hWnd);
return 0; if (!Wnd)
return 0;
if (ProcessId != GetCurrentProcessId()) if (Wnd->pi != g_kpi)
{ {
/* do not send WM_GETTEXT messages to other processes */
LPWSTR Buffer;
INT Length; INT Length;
Buffer = HeapAlloc(GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR)); if (nMaxCount <= 0)
if (!Buffer) return 0;
return FALSE;
Length = NtUserInternalGetWindowText(hWnd, Buffer, nMaxCount); /* do not send WM_GETTEXT messages to other processes */
if (Length > 0 && nMaxCount > 0 && Length = Wnd->WindowName.Length / sizeof(WCHAR);
!WideCharToMultiByte(CP_ACP, 0, Buffer, -1, if (Length != 0)
lpString, nMaxCount, NULL, NULL))
{ {
lpString[0] = '\0'; Buffer = DesktopPtrToUser(Wnd->WindowName.Buffer);
if (Buffer != NULL)
{
if (!WideCharToMultiByte(CP_ACP,
0,
Buffer,
Length + 1,
lpString,
nMaxCount,
NULL,
NULL))
{
lpString[nMaxCount - 1] = '\0';
}
}
else
{
Length = 0;
lpString[0] = '\0';
}
} }
HeapFree(GetProcessHeap(), 0, Buffer); else
lpString[0] = '\0';
return (LRESULT)Length; return (LRESULT)Length;
} }
@ -1074,19 +1093,7 @@ GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
int STDCALL int STDCALL
GetWindowTextLengthA(HWND hWnd) GetWindowTextLengthA(HWND hWnd)
{ {
DWORD ProcessId;
if(!NtUserGetWindowThreadProcessId(hWnd, &ProcessId))
{
return 0;
}
if(ProcessId == GetCurrentProcessId())
{
return(SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0)); return(SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0));
}
/* do not send WM_GETTEXT messages to other processes */
return (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
} }
@ -1096,19 +1103,7 @@ GetWindowTextLengthA(HWND hWnd)
int STDCALL int STDCALL
GetWindowTextLengthW(HWND hWnd) GetWindowTextLengthW(HWND hWnd)
{ {
DWORD ProcessId;
if(!NtUserGetWindowThreadProcessId(hWnd, &ProcessId))
{
return 0;
}
if(ProcessId == GetCurrentProcessId())
{
return(SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0)); return(SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0));
}
/* do not send WM_GETTEXT messages to other processes */
return (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
} }
@ -1118,18 +1113,47 @@ GetWindowTextLengthW(HWND hWnd)
int STDCALL int STDCALL
GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount) GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
{ {
DWORD ProcessId; PWINDOW Wnd;
PCWSTR Buffer;
if (lpString == NULL) if (lpString == NULL)
return 0; return 0;
if (!NtUserGetWindowThreadProcessId(hWnd, &ProcessId)) Wnd = ValidateHwnd(hWnd);
return 0; if (!Wnd)
return 0;
if (ProcessId == GetCurrentProcessId()) if (Wnd->pi != g_kpi)
return SendMessageW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString); {
INT Length;
return NtUserInternalGetWindowText(hWnd, lpString, nMaxCount); if (nMaxCount <= 0)
return 0;
/* do not send WM_GETTEXT messages to other processes */
Length = Wnd->WindowName.Length / sizeof(WCHAR);
if (Length != 0)
{
Buffer = DesktopPtrToUser(Wnd->WindowName.Buffer);
if (Buffer != NULL)
{
RtlCopyMemory(lpString,
Buffer,
(Length + 1) * sizeof(WCHAR));
}
else
{
Length = 0;
lpString[0] = L'\0';
}
}
else
lpString[0] = L'\0';
return (LRESULT)Length;
}
return SendMessageW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
} }
DWORD STDCALL DWORD STDCALL
@ -1643,7 +1667,10 @@ int
STDCALL STDCALL
InternalGetWindowText(HWND hWnd, LPWSTR lpString, int nMaxCount) InternalGetWindowText(HWND hWnd, LPWSTR lpString, int nMaxCount)
{ {
return NtUserInternalGetWindowText(hWnd, lpString, nMaxCount); INT Ret = NtUserInternalGetWindowText(hWnd, lpString, nMaxCount);
if (Ret == 0)
*lpString = L'\0';
return Ret;
} }
/* /*

View file

@ -77,6 +77,10 @@ typedef struct _WINDOW
/* Window menu handle or window id */ /* Window menu handle or window id */
UINT IDMenu; UINT IDMenu;
LONG UserData; LONG UserData;
/* Pointer to the window class. */
PWINDOWCLASS Class;
/* Window name. */
UNICODE_STRING WindowName;
} WINDOW, *PWINDOW; } WINDOW, *PWINDOW;
typedef struct _W32PROCESSINFO typedef struct _W32PROCESSINFO

View file

@ -45,10 +45,6 @@ typedef struct _WINDOW_OBJECT
}; };
/* Indicates whether the window is derived from a system class */ /* Indicates whether the window is derived from a system class */
BOOL IsSystem; BOOL IsSystem;
/* Pointer to the window class. */
PWINDOWCLASS Class;
/* Window name. */
UNICODE_STRING WindowName;
/* Context help id */ /* Context help id */
DWORD ContextHelpId; DWORD ContextHelpId;
/* system menu handle. */ /* system menu handle. */

View file

@ -1927,11 +1927,11 @@ NtUserGetClassLong(IN HWND hWnd,
Window = UserGetWindowObject(hWnd); Window = UserGetWindowObject(hWnd);
if (Window != NULL) if (Window != NULL)
{ {
Ret = UserGetClassLongPtr(Window->Class, Ret = UserGetClassLongPtr(Window->Wnd->Class,
Offset, Offset,
Ansi); Ansi);
if (Ret != 0 && Offset == GCLP_MENUNAME && Window->Class->MenuNameIsString) if (Ret != 0 && Offset == GCLP_MENUNAME && Window->Wnd->Class->MenuNameIsString)
{ {
Ret = (ULONG_PTR)UserHeapAddressToUser((PVOID)Ret); Ret = (ULONG_PTR)UserHeapAddressToUser((PVOID)Ret);
} }
@ -2005,7 +2005,7 @@ InvalidParameter:
dwNewLong = (ULONG_PTR)&Value; dwNewLong = (ULONG_PTR)&Value;
} }
Ret = UserSetClassLongPtr(Window->Class, Ret = UserSetClassLongPtr(Window->Wnd->Class,
Offset, Offset,
dwNewLong, dwNewLong,
Ansi); Ansi);
@ -2218,7 +2218,7 @@ NtUserGetClassName (IN HWND hWnd,
CapturedClassName = *ClassName; CapturedClassName = *ClassName;
/* get the class name */ /* get the class name */
Ret = UserGetClassName(Window->Class, Ret = UserGetClassName(Window->Wnd->Class,
&CapturedClassName, &CapturedClassName,
Ansi); Ansi);

View file

@ -1357,7 +1357,7 @@ NtUserPaintDesktop(HDC hDC)
RETURN(FALSE); RETURN(FALSE);
} }
DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Class, GCL_HBRBACKGROUND, FALSE); DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Wnd->Class, GCL_HBRBACKGROUND, FALSE);
/* /*

View file

@ -152,7 +152,6 @@ co_IntSetForegroundAndFocusWindow(PWINDOW_OBJECT Window, PWINDOW_OBJECT FocusWin
ASSERT_REFS_CO(Window); ASSERT_REFS_CO(Window);
DPRINT("IntSetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, hWndFocus, MouseActivate ? "TRUE" : "FALSE"); DPRINT("IntSetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, hWndFocus, MouseActivate ? "TRUE" : "FALSE");
DPRINT("(%wZ)\n", &Window->WindowName);
Wnd = Window->Wnd; Wnd = Window->Wnd;
@ -426,8 +425,6 @@ NtUserSetActiveWindow(HWND hWnd)
RETURN( 0); RETURN( 0);
} }
DPRINT("(%wZ)\n", &Window->WindowName);
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetCurrentThreadWin32Thread()->MessageQueue; ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetCurrentThreadWin32Thread()->MessageQueue;
if (Window->MessageQueue != ThreadQueue) if (Window->MessageQueue != ThreadQueue)

View file

@ -603,7 +603,7 @@ co_IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg, USHORT *
{ {
/* generate double click messages, if necessary */ /* generate double click messages, if necessary */
if ((((*HitTest) != HTCLIENT) || if ((((*HitTest) != HTCLIENT) ||
(Window->Class->Style & CS_DBLCLKS)) && (Window->Wnd->Class->Style & CS_DBLCLKS)) &&
MsqIsDblClk(Msg, Remove)) MsqIsDblClk(Msg, Remove))
{ {
Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN; Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN;

View file

@ -1528,12 +1528,12 @@ UserDrawSysMenuButton(
/* Get the icon to draw. We don't care about WM_GETICON here. */ /* Get the icon to draw. We don't care about WM_GETICON here. */
hIcon = pWnd->Class->hIconSm; hIcon = pWnd->Wnd->Class->hIconSm;
if(!hIcon) if(!hIcon)
{ {
DPRINT("Wnd class has no small icon.\n"); DPRINT("Wnd class has no small icon.\n");
hIcon = pWnd->Class->hIcon; hIcon = pWnd->Wnd->Class->hIcon;
} }
if(!hIcon) if(!hIcon)
@ -1864,7 +1864,7 @@ BOOL UserDrawCaption(
if (str) if (str)
UserDrawCaptionText(hMemDc, str, &r, uFlags); UserDrawCaptionText(hMemDc, str, &r, uFlags);
else if (pWnd != NULL) else if (pWnd != NULL)
UserDrawCaptionText(hMemDc, &pWnd->WindowName, &r, uFlags); UserDrawCaptionText(hMemDc, &pWnd->Wnd->WindowName, &r, uFlags);
} }
if(!NtGdiBitBlt(hDc, lpRc->left, lpRc->top, if(!NtGdiBitBlt(hDc, lpRc->left, lpRc->top,

View file

@ -401,7 +401,7 @@ UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
if (!(Flags & DCX_WINDOW)) if (!(Flags & DCX_WINDOW))
{ {
if (Window->Class->Style & CS_PARENTDC) if (Wnd->Class->Style & CS_PARENTDC)
{ {
Flags |= DCX_PARENTCLIP; Flags |= DCX_PARENTCLIP;
} }
@ -739,7 +739,7 @@ DceFreeWindowDCE(PWINDOW_OBJECT Window)
{ {
if (pDCE == Window->Dce) /* owned or Class DCE*/ if (pDCE == Window->Dce) /* owned or Class DCE*/
{ {
if (Window->Class->Style & CS_OWNDC) /* owned DCE*/ if (Window->Wnd->Class->Style & CS_OWNDC) /* owned DCE*/
{ {
pDCE = DceFreeDCE(pDCE, FALSE); pDCE = DceFreeDCE(pDCE, FALSE);
Window->Dce = NULL; Window->Dce = NULL;

View file

@ -296,6 +296,7 @@ static VOID
UserFreeWindowInfo(PW32THREADINFO ti, PWINDOW_OBJECT WindowObject) UserFreeWindowInfo(PW32THREADINFO ti, PWINDOW_OBJECT WindowObject)
{ {
PW32CLIENTINFO ClientInfo = GetWin32ClientInfo(); PW32CLIENTINFO ClientInfo = GetWin32ClientInfo();
PWINDOW Wnd = WindowObject->Wnd;
if (ClientInfo->pvWND == DesktopHeapAddressToUser(WindowObject->Wnd)) if (ClientInfo->pvWND == DesktopHeapAddressToUser(WindowObject->Wnd))
{ {
@ -303,7 +304,16 @@ UserFreeWindowInfo(PW32THREADINFO ti, PWINDOW_OBJECT WindowObject)
ClientInfo->pvWND = NULL; ClientInfo->pvWND = NULL;
} }
DesktopHeapFree(ti->Desktop, WindowObject->Wnd); if (Wnd->WindowName.Buffer != NULL)
{
Wnd->WindowName.Length = 0;
Wnd->WindowName.MaximumLength = 0;
DesktopHeapFree(Wnd->ti->Desktop,
Wnd->WindowName.Buffer);
Wnd->WindowName.Buffer = NULL;
}
DesktopHeapFree(ti->Desktop, Wnd);
WindowObject->Wnd = NULL; WindowObject->Wnd = NULL;
} }
@ -453,18 +463,16 @@ static LRESULT co_UserFreeWindow(PWINDOW_OBJECT Window,
IntDestroyScrollBars(Window); IntDestroyScrollBars(Window);
/* dereference the class */ /* dereference the class */
IntDereferenceClass(Window->Class, IntDereferenceClass(Wnd->Class,
Window->ti->Desktop, Window->ti->Desktop,
Window->ti->kpi); Window->ti->kpi);
Window->Class = NULL; Wnd->Class = NULL;
if(Window->WindowRegion) if(Window->WindowRegion)
{ {
NtGdiDeleteObject(Window->WindowRegion); NtGdiDeleteObject(Window->WindowRegion);
} }
RtlFreeUnicodeString(&Window->WindowName);
ASSERT(Window->Wnd != NULL); ASSERT(Window->Wnd != NULL);
UserFreeWindowInfo(Window->ti, Window); UserFreeWindowInfo(Window->ti, Window);
@ -507,6 +515,8 @@ static WNDPROC
IntGetWindowProc(IN PWINDOW_OBJECT Window, IntGetWindowProc(IN PWINDOW_OBJECT Window,
IN BOOL Ansi) IN BOOL Ansi)
{ {
PWINDOW Wnd = Window->Wnd;
ASSERT(UserIsEnteredExclusive() == TRUE); ASSERT(UserIsEnteredExclusive() == TRUE);
if (Window->IsSystem) if (Window->IsSystem)
@ -529,22 +539,22 @@ IntGetWindowProc(IN PWINDOW_OBJECT Window,
{ {
PCALLPROC NewCallProc, CallProc; PCALLPROC NewCallProc, CallProc;
NewCallProc = UserFindCallProc(Window->Class, NewCallProc = UserFindCallProc(Wnd->Class,
Window->WndProc, Window->WndProc,
Window->Unicode); Window->Unicode);
if (NewCallProc == NULL) if (NewCallProc == NULL)
{ {
NewCallProc = CreateCallProc(Window->ti->Desktop, NewCallProc = CreateCallProc(Wnd->ti->Desktop,
Window->WndProc, Window->WndProc,
Window->Unicode, Window->Unicode,
Window->ti->kpi); Wnd->ti->kpi);
if (NewCallProc == NULL) if (NewCallProc == NULL)
{ {
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return NULL; return NULL;
} }
UserAddCallProcToClass(Window->Class, UserAddCallProcToClass(Wnd->Class,
NewCallProc); NewCallProc);
} }
@ -569,7 +579,7 @@ IntGetWindowInfo(PWINDOW_OBJECT Window, PWINDOWINFO pwi)
pwi->dwExStyle = Wnd->ExStyle; pwi->dwExStyle = Wnd->ExStyle;
pwi->dwWindowStatus = (UserGetForegroundWindow() == Window->hSelf); /* WS_ACTIVECAPTION */ pwi->dwWindowStatus = (UserGetForegroundWindow() == Window->hSelf); /* WS_ACTIVECAPTION */
IntGetWindowBorderMeasures(Window, &pwi->cxWindowBorders, &pwi->cyWindowBorders); IntGetWindowBorderMeasures(Window, &pwi->cxWindowBorders, &pwi->cyWindowBorders);
pwi->atomWindowType = (Window->Class ? Window->Class->Atom : 0); pwi->atomWindowType = (Wnd->Class ? Wnd->Class->Atom : 0);
pwi->wCreatorVersion = 0x400; /* FIXME - return a real version number */ pwi->wCreatorVersion = 0x400; /* FIXME - return a real version number */
return TRUE; return TRUE;
} }
@ -1596,7 +1606,7 @@ AllocErr:
* Fill out the structure describing it. * Fill out the structure describing it.
*/ */
Window->ti = ti; Window->ti = ti;
Window->Class = Class; Wnd->Class = Class;
Class = NULL; Class = NULL;
Window->SystemMenu = (HMENU)0; Window->SystemMenu = (HMENU)0;
@ -1606,7 +1616,7 @@ AllocErr:
Window->hSelf = hWnd; Window->hSelf = hWnd;
if (!hMenu) if (!hMenu)
hMenu = Window->Class->hMenu; hMenu = Wnd->Class->hMenu;
if (0 != (dwStyle & WS_CHILD)) if (0 != (dwStyle & WS_CHILD))
{ {
@ -1634,18 +1644,18 @@ AllocErr:
Wnd->UserData = 0; Wnd->UserData = 0;
Window->IsSystem = Window->Class->System; Window->IsSystem = Wnd->Class->System;
if (Window->Class->System) if (Wnd->Class->System)
{ {
/* NOTE: Always create a unicode window for system classes! */ /* NOTE: Always create a unicode window for system classes! */
Window->Unicode = TRUE; Window->Unicode = TRUE;
Window->WndProc = Window->Class->WndProc; Window->WndProc = Wnd->Class->WndProc;
Window->WndProcExtra = Window->Class->WndProcExtra; Window->WndProcExtra = Wnd->Class->WndProcExtra;
} }
else else
{ {
Window->Unicode = Window->Class->Unicode; Window->Unicode = Wnd->Class->Unicode;
Window->WndProc = Window->Class->WndProc; Window->WndProc = Wnd->Class->WndProc;
Window->CallProc = NULL; Window->CallProc = NULL;
} }
@ -1654,28 +1664,35 @@ AllocErr:
Window->LastChild = NULL; Window->LastChild = NULL;
Window->PrevSibling = NULL; Window->PrevSibling = NULL;
Window->NextSibling = NULL; Window->NextSibling = NULL;
Wnd->ExtraDataSize = Window->Class->WndExtra; Wnd->ExtraDataSize = Wnd->Class->WndExtra;
InitializeListHead(&Window->PropListHead); InitializeListHead(&Window->PropListHead);
InitializeListHead(&Window->WndObjListHead); InitializeListHead(&Window->WndObjListHead);
if (NULL != WindowName->Buffer) if (NULL != WindowName->Buffer && WindowName->Length > 0)
{ {
Window->WindowName.MaximumLength = WindowName->MaximumLength; Wnd->WindowName.Buffer = DesktopHeapAlloc(Wnd->ti->Desktop,
Window->WindowName.Length = WindowName->Length; WindowName->Length + sizeof(UNICODE_NULL));
Window->WindowName.Buffer = ExAllocatePoolWithTag(PagedPool, WindowName->MaximumLength, if (Wnd->WindowName.Buffer == NULL)
TAG_STRING);
if (NULL == Window->WindowName.Buffer)
{ {
DPRINT1("Failed to allocate mem for window name\n"); SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); RETURN( (HWND)0);
RETURN( NULL);
} }
RtlCopyMemory(Window->WindowName.Buffer, WindowName->Buffer, WindowName->MaximumLength);
} Wnd->WindowName.Buffer[WindowName->Length / sizeof(WCHAR)] = L'\0';
else _SEH_TRY
{ {
RtlInitUnicodeString(&Window->WindowName, NULL); RtlCopyMemory(Wnd->WindowName.Buffer,
WindowName->Buffer,
WindowName->Length);
Wnd->WindowName.Length = WindowName->Length;
}
_SEH_HANDLE
{
WindowName->Length = 0;
Wnd->WindowName.Buffer[0] = L'\0';
}
_SEH_END;
} }
/* /*
@ -2459,8 +2476,8 @@ IntFindWindow(PWINDOW_OBJECT Parent,
/* Do not send WM_GETTEXT messages in the kernel mode version! /* Do not send WM_GETTEXT messages in the kernel mode version!
The user mode version however calls GetWindowText() which will The user mode version however calls GetWindowText() which will
send WM_GETTEXT messages to windows belonging to its processes */ send WM_GETTEXT messages to windows belonging to its processes */
if((!CheckWindowName || !RtlCompareUnicodeString(WindowName, &(Child->WindowName), TRUE)) && if((!CheckWindowName || !RtlCompareUnicodeString(WindowName, &(Child->Wnd->WindowName), TRUE)) &&
(!ClassAtom || Child->Class->Atom == ClassAtom)) (!ClassAtom || Child->Wnd->Class->Atom == ClassAtom))
{ {
Ret = Child->hSelf; Ret = Child->hSelf;
break; break;
@ -2633,9 +2650,9 @@ NtUserFindWindowEx(HWND hwndParent,
The user mode version however calls GetWindowText() which will The user mode version however calls GetWindowText() which will
send WM_GETTEXT messages to windows belonging to its processes */ send WM_GETTEXT messages to windows belonging to its processes */
WindowMatches = !CheckWindowName || !RtlCompareUnicodeString( WindowMatches = !CheckWindowName || !RtlCompareUnicodeString(
&WindowName, &TopLevelWindow->WindowName, TRUE); &WindowName, &TopLevelWindow->Wnd->WindowName, TRUE);
ClassMatches = (ClassAtom == (RTL_ATOM)0) || ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
ClassAtom == TopLevelWindow->Class->Atom; ClassAtom == TopLevelWindow->Wnd->Class->Atom;
if (WindowMatches && ClassMatches) if (WindowMatches && ClassMatches)
{ {
@ -3574,6 +3591,7 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
{ {
WNDPROC Ret; WNDPROC Ret;
PCALLPROC CallProc; PCALLPROC CallProc;
PWINDOW Wnd = Window->Wnd;
/* resolve any callproc handle if possible */ /* resolve any callproc handle if possible */
if (IsCallProcHandle(NewWndProc)) if (IsCallProcHandle(NewWndProc))
@ -3601,7 +3619,7 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
} }
else else
{ {
CallProc = UserFindCallProc(Window->Class, CallProc = UserFindCallProc(Wnd->Class,
Window->WndProc, Window->WndProc,
Window->Unicode); Window->Unicode);
if (CallProc == NULL) if (CallProc == NULL)
@ -3609,14 +3627,14 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
CallProc = CreateCallProc(NULL, CallProc = CreateCallProc(NULL,
Window->WndProc, Window->WndProc,
Window->Unicode, Window->Unicode,
Window->ti->kpi); Wnd->ti->kpi);
if (CallProc == NULL) if (CallProc == NULL)
{ {
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return NULL; return NULL;
} }
UserAddCallProcToClass(Window->Class, UserAddCallProcToClass(Wnd->Class,
CallProc); CallProc);
} }
@ -3626,17 +3644,17 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
} }
} }
if (Window->Class->System) if (Wnd->Class->System)
{ {
/* check if the new procedure matches with the one in the /* check if the new procedure matches with the one in the
window class. If so, we need to restore both procedures! */ window class. If so, we need to restore both procedures! */
Window->IsSystem = (NewWndProc == Window->Class->WndProc || Window->IsSystem = (NewWndProc == Wnd->Class->WndProc ||
NewWndProc == Window->Class->WndProcExtra); NewWndProc == Wnd->Class->WndProcExtra);
if (Window->IsSystem) if (Window->IsSystem)
{ {
Window->WndProc = Window->Class->WndProc; Window->WndProc = Wnd->Class->WndProc;
Window->WndProcExtra = Window->Class->WndProcExtra; Window->WndProcExtra = Wnd->Class->WndProcExtra;
Window->Unicode = !Ansi; Window->Unicode = !Ansi;
return Ret; return Ret;
} }
@ -4622,49 +4640,109 @@ BOOL STDCALL
NtUserDefSetText(HWND hWnd, PUNICODE_STRING WindowText) NtUserDefSetText(HWND hWnd, PUNICODE_STRING WindowText)
{ {
PWINDOW_OBJECT Window; PWINDOW_OBJECT Window;
PWINDOW Wnd;
UNICODE_STRING SafeText; UNICODE_STRING SafeText;
NTSTATUS Status; BOOL Ret = TRUE;
DECLARE_RETURN(INT);
DPRINT("Enter NtUserDefSetText\n"); DPRINT("Enter NtUserDefSetText\n");
RtlInitUnicodeString(&SafeText, NULL);
if (WindowText != NULL)
{
_SEH_TRY
{
SafeText = ProbeForReadUnicodeString(WindowText);
}
_SEH_HANDLE
{
Ret = FALSE;
SetLastNtError(_SEH_GetExceptionCode());
}
_SEH_END;
if (!Ret)
return FALSE;
}
UserEnterExclusive(); UserEnterExclusive();
if(!(Window = UserGetWindowObject(hWnd))) if(!(Window = UserGetWindowObject(hWnd)))
{ {
RETURN( FALSE); UserLeave();
return FALSE;
} }
Wnd = Window->Wnd;
if(WindowText) if(SafeText.Length != 0)
{ {
Status = IntSafeCopyUnicodeString(&SafeText, WindowText); _SEH_TRY
if(!NT_SUCCESS(Status))
{ {
SetLastNtError(Status); if (Wnd->WindowName.MaximumLength > 0 &&
RETURN( FALSE); SafeText.Length <= Wnd->WindowName.MaximumLength - sizeof(UNICODE_NULL))
{
ASSERT(Wnd->WindowName.Buffer != NULL);
Wnd->WindowName.Length = SafeText.Length;
Wnd->WindowName.Buffer[SafeText.Length / sizeof(WCHAR)] = L'\0';
RtlCopyMemory(Wnd->WindowName.Buffer,
SafeText.Buffer,
SafeText.Length);
}
else
{
PWCHAR buf;
Wnd->WindowName.MaximumLength = Wnd->WindowName.Length = 0;
buf = Wnd->WindowName.Buffer;
Wnd->WindowName.Buffer = NULL;
if (buf != NULL)
{
DesktopHeapFree(Wnd->ti->Desktop,
buf);
}
Wnd->WindowName.Buffer = DesktopHeapAlloc(Wnd->ti->Desktop,
SafeText.Length + sizeof(UNICODE_NULL));
if (Wnd->WindowName.Buffer != NULL)
{
Wnd->WindowName.Buffer[SafeText.Length / sizeof(WCHAR)] = L'\0';
RtlCopyMemory(Wnd->WindowName.Buffer,
SafeText.Buffer,
SafeText.Length);
Wnd->WindowName.MaximumLength = SafeText.Length + sizeof(UNICODE_NULL);
Wnd->WindowName.Length = SafeText.Length;
}
else
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
Ret = FALSE;
}
}
} }
_SEH_HANDLE
{
SetLastNtError(_SEH_GetExceptionCode());
Ret = FALSE;
}
_SEH_END;
} }
else else
{ {
RtlInitUnicodeString(&SafeText, NULL); Wnd->WindowName.Length = 0;
if (Wnd->WindowName.Buffer != NULL)
Wnd->WindowName.Buffer[0] = L'\0';
} }
/* FIXME - do this thread-safe! otherwise one could crash here! */
RtlFreeUnicodeString(&Window->WindowName);
Window->WindowName = SafeText;
/* Send shell notifications */ /* Send shell notifications */
if (!IntGetOwner(Window) && !IntGetParent(Window)) if (!IntGetOwner(Window) && !IntGetParent(Window))
{ {
co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd); co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd);
} }
RETURN( TRUE); Ret = TRUE;
CLEANUP: DPRINT("Leave NtUserDefSetText, ret=%i\n", Ret);
DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_);
UserLeave(); UserLeave();
END_CLEANUP; return Ret;
} }
/* /*
@ -4678,6 +4756,7 @@ INT STDCALL
NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount) NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount)
{ {
PWINDOW_OBJECT Window; PWINDOW_OBJECT Window;
PWINDOW Wnd;
NTSTATUS Status; NTSTATUS Status;
INT Result; INT Result;
DECLARE_RETURN(INT); DECLARE_RETURN(INT);
@ -4695,9 +4774,9 @@ NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount)
{ {
RETURN( 0); RETURN( 0);
} }
Wnd = Window->Wnd;
/* FIXME - do this thread-safe! otherwise one could crash here! */ Result = Wnd->WindowName.Length / sizeof(WCHAR);
Result = Window->WindowName.Length / sizeof(WCHAR);
if(lpString) if(lpString)
{ {
const WCHAR Terminator = L'\0'; const WCHAR Terminator = L'\0';
@ -4707,7 +4786,7 @@ NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount)
Copy = min(nMaxCount - 1, Result); Copy = min(nMaxCount - 1, Result);
if(Copy > 0) if(Copy > 0)
{ {
Status = MmCopyToCaller(Buffer, Window->WindowName.Buffer, Copy * sizeof(WCHAR)); Status = MmCopyToCaller(Buffer, Wnd->WindowName.Buffer, Copy * sizeof(WCHAR));
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
SetLastNtError(Status); SetLastNtError(Status);