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

View file

@ -1035,31 +1035,50 @@ GetWindowRect(HWND hWnd,
int STDCALL
GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
{
DWORD ProcessId;
PWINDOW Wnd;
PCWSTR Buffer;
if (lpString == NULL)
return 0;
if (!NtUserGetWindowThreadProcessId(hWnd, &ProcessId))
return 0;
Wnd = ValidateHwnd(hWnd);
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;
Buffer = HeapAlloc(GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR));
if (!Buffer)
return FALSE;
Length = NtUserInternalGetWindowText(hWnd, Buffer, nMaxCount);
if (Length > 0 && nMaxCount > 0 &&
!WideCharToMultiByte(CP_ACP, 0, Buffer, -1,
lpString, nMaxCount, NULL, NULL))
if (nMaxCount <= 0)
return 0;
/* do not send WM_GETTEXT messages to other processes */
Length = Wnd->WindowName.Length / sizeof(WCHAR);
if (Length != 0)
{
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;
}
@ -1074,19 +1093,7 @@ GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
int STDCALL
GetWindowTextLengthA(HWND hWnd)
{
DWORD ProcessId;
if(!NtUserGetWindowThreadProcessId(hWnd, &ProcessId))
{
return 0;
}
if(ProcessId == GetCurrentProcessId())
{
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
GetWindowTextLengthW(HWND hWnd)
{
DWORD ProcessId;
if(!NtUserGetWindowThreadProcessId(hWnd, &ProcessId))
{
return 0;
}
if(ProcessId == GetCurrentProcessId())
{
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
GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
{
DWORD ProcessId;
PWINDOW Wnd;
PCWSTR Buffer;
if (lpString == NULL)
return 0;
if (!NtUserGetWindowThreadProcessId(hWnd, &ProcessId))
return 0;
Wnd = ValidateHwnd(hWnd);
if (!Wnd)
return 0;
if (ProcessId == GetCurrentProcessId())
return SendMessageW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
if (Wnd->pi != g_kpi)
{
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
@ -1643,7 +1667,10 @@ int
STDCALL
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 */
UINT IDMenu;
LONG UserData;
/* Pointer to the window class. */
PWINDOWCLASS Class;
/* Window name. */
UNICODE_STRING WindowName;
} WINDOW, *PWINDOW;
typedef struct _W32PROCESSINFO

View file

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

View file

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

View file

@ -1357,7 +1357,7 @@ NtUserPaintDesktop(HDC hDC)
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);
DPRINT("IntSetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, hWndFocus, MouseActivate ? "TRUE" : "FALSE");
DPRINT("(%wZ)\n", &Window->WindowName);
Wnd = Window->Wnd;
@ -426,8 +425,6 @@ NtUserSetActiveWindow(HWND hWnd)
RETURN( 0);
}
DPRINT("(%wZ)\n", &Window->WindowName);
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetCurrentThreadWin32Thread()->MessageQueue;
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 */
if ((((*HitTest) != HTCLIENT) ||
(Window->Class->Style & CS_DBLCLKS)) &&
(Window->Wnd->Class->Style & CS_DBLCLKS)) &&
MsqIsDblClk(Msg, Remove))
{
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. */
hIcon = pWnd->Class->hIconSm;
hIcon = pWnd->Wnd->Class->hIconSm;
if(!hIcon)
{
DPRINT("Wnd class has no small icon.\n");
hIcon = pWnd->Class->hIcon;
hIcon = pWnd->Wnd->Class->hIcon;
}
if(!hIcon)
@ -1864,7 +1864,7 @@ BOOL UserDrawCaption(
if (str)
UserDrawCaptionText(hMemDc, str, &r, uFlags);
else if (pWnd != NULL)
UserDrawCaptionText(hMemDc, &pWnd->WindowName, &r, uFlags);
UserDrawCaptionText(hMemDc, &pWnd->Wnd->WindowName, &r, uFlags);
}
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 (Window->Class->Style & CS_PARENTDC)
if (Wnd->Class->Style & CS_PARENTDC)
{
Flags |= DCX_PARENTCLIP;
}
@ -739,7 +739,7 @@ DceFreeWindowDCE(PWINDOW_OBJECT Window)
{
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);
Window->Dce = NULL;

View file

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