diff --git a/reactos/dll/win32/user32/windows/defwnd.c b/reactos/dll/win32/user32/windows/defwnd.c index 573d8ecadb3..1e29258ef55 100644 --- a/reactos/dll/win32/user32/windows/defwnd.c +++ b/reactos/dll/win32/user32/windows/defwnd.c @@ -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; } diff --git a/reactos/dll/win32/user32/windows/window.c b/reactos/dll/win32/user32/windows/window.c index abc58a81ef0..b2705daa5f3 100644 --- a/reactos/dll/win32/user32/windows/window.c +++ b/reactos/dll/win32/user32/windows/window.c @@ -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; } /* diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index 3d26357e8d1..8974c232c89 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -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 diff --git a/reactos/subsystems/win32/win32k/include/window.h b/reactos/subsystems/win32/win32k/include/window.h index 737e0304133..a074b0cd96b 100644 --- a/reactos/subsystems/win32/win32k/include/window.h +++ b/reactos/subsystems/win32/win32k/include/window.h @@ -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. */ diff --git a/reactos/subsystems/win32/win32k/ntuser/class.c b/reactos/subsystems/win32/win32k/ntuser/class.c index 3d87d5a042e..b4dd7f421ce 100644 --- a/reactos/subsystems/win32/win32k/ntuser/class.c +++ b/reactos/subsystems/win32/win32k/ntuser/class.c @@ -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); diff --git a/reactos/subsystems/win32/win32k/ntuser/desktop.c b/reactos/subsystems/win32/win32k/ntuser/desktop.c index 24b324cbc41..36997cfe399 100644 --- a/reactos/subsystems/win32/win32k/ntuser/desktop.c +++ b/reactos/subsystems/win32/win32k/ntuser/desktop.c @@ -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); /* diff --git a/reactos/subsystems/win32/win32k/ntuser/focus.c b/reactos/subsystems/win32/win32k/ntuser/focus.c index 090aa45acf9..5d2592ab867 100644 --- a/reactos/subsystems/win32/win32k/ntuser/focus.c +++ b/reactos/subsystems/win32/win32k/ntuser/focus.c @@ -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) diff --git a/reactos/subsystems/win32/win32k/ntuser/message.c b/reactos/subsystems/win32/win32k/ntuser/message.c index 236cae2321f..dc8e84356dd 100644 --- a/reactos/subsystems/win32/win32k/ntuser/message.c +++ b/reactos/subsystems/win32/win32k/ntuser/message.c @@ -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; diff --git a/reactos/subsystems/win32/win32k/ntuser/painting.c b/reactos/subsystems/win32/win32k/ntuser/painting.c index 2397eaa2f68..01e96573d55 100644 --- a/reactos/subsystems/win32/win32k/ntuser/painting.c +++ b/reactos/subsystems/win32/win32k/ntuser/painting.c @@ -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, diff --git a/reactos/subsystems/win32/win32k/ntuser/windc.c b/reactos/subsystems/win32/win32k/ntuser/windc.c index 8c48fd4dbd8..3fa9556f2da 100644 --- a/reactos/subsystems/win32/win32k/ntuser/windc.c +++ b/reactos/subsystems/win32/win32k/ntuser/windc.c @@ -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; diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index f482d0fdf4c..dd40556f082 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -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);