Author: weiden Date: Fri Nov 16 05:37:14 2007 New Revision: 30490
URL: http://svn.reactos.org/svn/reactos?rev=30490&view=rev Log: Optimize GetWindowText(Length)A/W and WM_GETTEXT(LENGTH)
Modified: trunk/reactos/dll/win32/user32/windows/defwnd.c 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/class.c trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c trunk/reactos/subsystems/win32/win32k/ntuser/focus.c trunk/reactos/subsystems/win32/win32k/ntuser/message.c trunk/reactos/subsystems/win32/win32k/ntuser/painting.c trunk/reactos/subsystems/win32/win32k/ntuser/windc.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c
Modified: trunk/reactos/dll/win32/user32/windows/defwnd.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/de... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/defwnd.c (original) +++ trunk/reactos/dll/win32/user32/windows/defwnd.c Fri Nov 16 05:37:14 2007 @@ -1602,6 +1602,7 @@ LPARAM lParam) { LRESULT Result = 0; + PWINDOW Wnd;
SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam); switch (Msg) @@ -1630,33 +1631,57 @@
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; - - Buffer = HeapAlloc(GetProcessHeap(), 0, wParam * sizeof(WCHAR)); - if (!Buffer) - { - 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'; - } - - HeapFree(GetProcessHeap(), 0, Buffer); - - Result = (LRESULT)Length; + PWSTR buf = NULL; + PSTR outbuf = (PSTR)lParam; + UINT copy; + + 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) + { + 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 @@ LPARAM lParam) { LRESULT Result = 0; + PWINDOW Wnd;
SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam); switch (Msg) @@ -1732,13 +1758,51 @@
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; }
Modified: trunk/reactos/dll/win32/user32/windows/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/wi... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/window.c (original) +++ trunk/reactos/dll/win32/user32/windows/window.c Fri Nov 16 05:37:14 2007 @@ -1035,31 +1035,50 @@ 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; - - if (ProcessId != GetCurrentProcessId()) + Wnd = ValidateHwnd(hWnd); + if (!Wnd) + return 0; + + if (Wnd->pi != g_kpi) { + INT Length; + + if (nMaxCount <= 0) + return 0; + /* 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)) + 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 @@ 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 @@ 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 @@ 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; - - if (ProcessId == GetCurrentProcessId()) - return SendMessageW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString); - - return NtUserInternalGetWindowText(hWnd, lpString, nMaxCount); + Wnd = ValidateHwnd(hWnd); + if (!Wnd) + return 0; + + if (Wnd->pi != g_kpi) + { + INT Length; + + 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 @@ 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; }
/*
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntus... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h Fri Nov 16 05:37:14 2007 @@ -77,6 +77,10 @@ /* 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
Modified: trunk/reactos/subsystems/win32/win32k/include/window.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/window.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/window.h Fri Nov 16 05:37:14 2007 @@ -45,10 +45,6 @@ }; /* 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. */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/class.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/class.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/class.c Fri Nov 16 05:37:14 2007 @@ -1927,11 +1927,11 @@ 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 @@ dwNewLong = (ULONG_PTR)&Value; }
- Ret = UserSetClassLongPtr(Window->Class, + Ret = UserSetClassLongPtr(Window->Wnd->Class, Offset, dwNewLong, Ansi); @@ -2218,7 +2218,7 @@ CapturedClassName = *ClassName;
/* get the class name */ - Ret = UserGetClassName(Window->Class, + Ret = UserGetClassName(Window->Wnd->Class, &CapturedClassName, Ansi);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c Fri Nov 16 05:37:14 2007 @@ -1357,7 +1357,7 @@ RETURN(FALSE); }
- DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Class, GCL_HBRBACKGROUND, FALSE); + DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Wnd->Class, GCL_HBRBACKGROUND, FALSE);
/*
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/focus.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/focus.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/focus.c Fri Nov 16 05:37:14 2007 @@ -152,7 +152,6 @@ 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 @@ RETURN( 0); }
- DPRINT("(%wZ)\n", &Window->WindowName); - ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetCurrentThreadWin32Thread()->MessageQueue;
if (Window->MessageQueue != ThreadQueue)
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/message.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c Fri Nov 16 05:37:14 2007 @@ -603,7 +603,7 @@ { /* 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;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/painting.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/painting.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/painting.c Fri Nov 16 05:37:14 2007 @@ -1528,12 +1528,12 @@
/* 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 @@ 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,
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/windc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/windc.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/windc.c Fri Nov 16 05:37:14 2007 @@ -401,7 +401,7 @@
if (!(Flags & DCX_WINDOW)) { - if (Window->Class->Style & CS_PARENTDC) + if (Wnd->Class->Style & CS_PARENTDC) { Flags |= DCX_PARENTCLIP; } @@ -739,7 +739,7 @@ { 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;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c Fri Nov 16 05:37:14 2007 @@ -296,6 +296,7 @@ UserFreeWindowInfo(PW32THREADINFO ti, PWINDOW_OBJECT WindowObject) { PW32CLIENTINFO ClientInfo = GetWin32ClientInfo(); + PWINDOW Wnd = WindowObject->Wnd;
if (ClientInfo->pvWND == DesktopHeapAddressToUser(WindowObject->Wnd)) { @@ -303,7 +304,16 @@ 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,17 +463,15 @@ 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 @@ IntGetWindowProc(IN PWINDOW_OBJECT Window, IN BOOL Ansi) { + PWINDOW Wnd = Window->Wnd; + ASSERT(UserIsEnteredExclusive() == TRUE);
if (Window->IsSystem) @@ -529,22 +539,22 @@ { 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 @@ 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 @@ * 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 @@ Window->hSelf = hWnd;
if (!hMenu) - hMenu = Window->Class->hMenu; + hMenu = Wnd->Class->hMenu;
if (0 != (dwStyle & WS_CHILD)) { @@ -1634,18 +1644,18 @@
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 @@ 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) - { - Window->WindowName.MaximumLength = WindowName->MaximumLength; - Window->WindowName.Length = WindowName->Length; - Window->WindowName.Buffer = ExAllocatePoolWithTag(PagedPool, WindowName->MaximumLength, - TAG_STRING); - if (NULL == Window->WindowName.Buffer) - { - DPRINT1("Failed to allocate mem for window name\n"); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - RETURN( NULL); - } - RtlCopyMemory(Window->WindowName.Buffer, WindowName->Buffer, WindowName->MaximumLength); - } - else - { - RtlInitUnicodeString(&Window->WindowName, NULL); + if (NULL != WindowName->Buffer && WindowName->Length > 0) + { + Wnd->WindowName.Buffer = DesktopHeapAlloc(Wnd->ti->Desktop, + WindowName->Length + sizeof(UNICODE_NULL)); + if (Wnd->WindowName.Buffer == NULL) + { + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + RETURN( (HWND)0); + } + + 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 @@ /* 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 @@ 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 @@ { WNDPROC Ret; PCALLPROC CallProc; + PWINDOW Wnd = Window->Wnd;
/* resolve any callproc handle if possible */ if (IsCallProcHandle(NewWndProc)) @@ -3601,7 +3619,7 @@ } else { - CallProc = UserFindCallProc(Window->Class, + CallProc = UserFindCallProc(Wnd->Class, Window->WndProc, Window->Unicode); if (CallProc == NULL) @@ -3609,14 +3627,14 @@ 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 @@ } }
- 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,36 +4640,97 @@ 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); - } - - if(WindowText) - { - Status = IntSafeCopyUnicodeString(&SafeText, WindowText); - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - RETURN( FALSE); - } + UserLeave(); + return FALSE; + } + Wnd = Window->Wnd; + + if(SafeText.Length != 0) + { + _SEH_TRY + { + 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); - } - - /* FIXME - do this thread-safe! otherwise one could crash here! */ - RtlFreeUnicodeString(&Window->WindowName); - - Window->WindowName = SafeText; + Wnd->WindowName.Length = 0; + if (Wnd->WindowName.Buffer != NULL) + Wnd->WindowName.Buffer[0] = L'\0'; + }
/* Send shell notifications */ if (!IntGetOwner(Window) && !IntGetParent(Window)) @@ -4659,12 +4738,11 @@ co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) hWnd); }
- RETURN( TRUE); - -CLEANUP: - DPRINT("Leave NtUserDefSetText, ret=%i\n",_ret_); + Ret = TRUE; + + DPRINT("Leave NtUserDefSetText, ret=%i\n", Ret); UserLeave(); - END_CLEANUP; + return Ret; }
/* @@ -4678,6 +4756,7 @@ NtUserInternalGetWindowText(HWND hWnd, LPWSTR lpString, INT nMaxCount) { PWINDOW_OBJECT Window; + PWINDOW Wnd; NTSTATUS Status; INT Result; DECLARE_RETURN(INT); @@ -4695,9 +4774,9 @@ { RETURN( 0); } - - /* FIXME - do this thread-safe! otherwise one could crash here! */ - Result = Window->WindowName.Length / sizeof(WCHAR); + Wnd = Window->Wnd; + + Result = Wnd->WindowName.Length / sizeof(WCHAR); if(lpString) { const WCHAR Terminator = L'\0'; @@ -4707,7 +4786,7 @@ 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);