mirror of
https://github.com/reactos/reactos.git
synced 2024-07-07 21:25:05 +00:00
Bug 1507 patch from w3seek : This patch fixes more issues with NtUserFindWindowEx. (one example of bugs have been fixed with this patch is the tray icon)
svn path=/trunk/; revision=21956
This commit is contained in:
parent
6e418a0fd9
commit
3e649bb0dc
|
@ -69,6 +69,10 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName,
|
||||||
OUT PWINDOWCLASS *BaseClass OPTIONAL,
|
OUT PWINDOWCLASS *BaseClass OPTIONAL,
|
||||||
OUT PWINDOWCLASS **Link OPTIONAL);
|
OUT PWINDOWCLASS **Link OPTIONAL);
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
IntGetAtomFromStringOrAtom(IN PUNICODE_STRING ClassName,
|
||||||
|
OUT RTL_ATOM *Atom);
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
IntCheckProcessDesktopClasses(IN PDESKTOP Desktop,
|
IntCheckProcessDesktopClasses(IN PDESKTOP Desktop,
|
||||||
IN BOOL FreeOnFailure);
|
IN BOOL FreeOnFailure);
|
||||||
|
|
|
@ -835,12 +835,11 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassSize = sizeof(WINDOWCLASS) + lpwcx->cbClsExtra;
|
ClassSize = sizeof(WINDOWCLASS) + lpwcx->cbClsExtra;
|
||||||
ClassSize += ClassName->Length + sizeof(UNICODE_NULL);
|
|
||||||
ClassSize += MenuName->Length + sizeof(UNICODE_NULL);
|
|
||||||
if (ClassName->Length != 0)
|
|
||||||
ClassSize += RtlUnicodeStringToAnsiSize(ClassName);
|
|
||||||
if (MenuName->Length != 0)
|
if (MenuName->Length != 0)
|
||||||
|
{
|
||||||
|
ClassSize += MenuName->Length + sizeof(UNICODE_NULL);
|
||||||
ClassSize += RtlUnicodeStringToAnsiSize(MenuName);
|
ClassSize += RtlUnicodeStringToAnsiSize(MenuName);
|
||||||
|
}
|
||||||
|
|
||||||
if (Desktop != NULL)
|
if (Desktop != NULL)
|
||||||
{
|
{
|
||||||
|
@ -996,14 +995,11 @@ IntFindClass(IN RTL_ATOM Atom,
|
||||||
return Class;
|
return Class;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTL_ATOM
|
BOOL
|
||||||
IntGetClassAtom(IN PUNICODE_STRING ClassName,
|
IntGetAtomFromStringOrAtom(IN PUNICODE_STRING ClassName,
|
||||||
IN HINSTANCE hInstance OPTIONAL,
|
OUT RTL_ATOM *Atom)
|
||||||
IN PW32PROCESSINFO pi OPTIONAL,
|
|
||||||
OUT PWINDOWCLASS *BaseClass OPTIONAL,
|
|
||||||
OUT PWINDOWCLASS **Link OPTIONAL)
|
|
||||||
{
|
{
|
||||||
RTL_ATOM Atom = (RTL_ATOM)0;
|
BOOL Ret = FALSE;
|
||||||
|
|
||||||
if (ClassName->Length != 0)
|
if (ClassName->Length != 0)
|
||||||
{
|
{
|
||||||
|
@ -1038,8 +1034,12 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName,
|
||||||
/* lookup the atom */
|
/* lookup the atom */
|
||||||
Status = RtlLookupAtomInAtomTable(gAtomTable,
|
Status = RtlLookupAtomInAtomTable(gAtomTable,
|
||||||
AtomName,
|
AtomName,
|
||||||
&Atom);
|
Atom);
|
||||||
if (!NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Ret = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||||
{
|
{
|
||||||
|
@ -1054,10 +1054,25 @@ IntGetClassAtom(IN PUNICODE_STRING ClassName,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(IS_ATOM(ClassName->Buffer));
|
ASSERT(IS_ATOM(ClassName->Buffer));
|
||||||
Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer);
|
*Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer);
|
||||||
|
Ret = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BaseClass != NULL && Atom != (RTL_ATOM)0)
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTL_ATOM
|
||||||
|
IntGetClassAtom(IN PUNICODE_STRING ClassName,
|
||||||
|
IN HINSTANCE hInstance OPTIONAL,
|
||||||
|
IN PW32PROCESSINFO pi OPTIONAL,
|
||||||
|
OUT PWINDOWCLASS *BaseClass OPTIONAL,
|
||||||
|
OUT PWINDOWCLASS **Link OPTIONAL)
|
||||||
|
{
|
||||||
|
RTL_ATOM Atom = (RTL_ATOM)0;
|
||||||
|
|
||||||
|
if (IntGetAtomFromStringOrAtom(ClassName,
|
||||||
|
&Atom) &&
|
||||||
|
BaseClass != NULL && Atom != (RTL_ATOM)0)
|
||||||
{
|
{
|
||||||
PWINDOWCLASS Class;
|
PWINDOWCLASS Class;
|
||||||
|
|
||||||
|
|
|
@ -2344,7 +2344,7 @@ NtUserFillWindow(DWORD Unknown0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HWND FASTCALL
|
static HWND FASTCALL
|
||||||
IntFindWindow(PWINDOW_OBJECT Parent,
|
IntFindWindow(PWINDOW_OBJECT Parent,
|
||||||
PWINDOW_OBJECT ChildAfter,
|
PWINDOW_OBJECT ChildAfter,
|
||||||
RTL_ATOM ClassAtom,
|
RTL_ATOM ClassAtom,
|
||||||
|
@ -2356,7 +2356,7 @@ IntFindWindow(PWINDOW_OBJECT Parent,
|
||||||
|
|
||||||
ASSERT(Parent);
|
ASSERT(Parent);
|
||||||
|
|
||||||
CheckWindowName = (WindowName && (WindowName->Length > 0));
|
CheckWindowName = WindowName->Length != 0;
|
||||||
|
|
||||||
if((List = IntWinListChildren(Parent)))
|
if((List = IntWinListChildren(Parent)))
|
||||||
{
|
{
|
||||||
|
@ -2425,15 +2425,67 @@ NtUserFindWindowEx(HWND hwndParent,
|
||||||
PUNICODE_STRING ucWindowName)
|
PUNICODE_STRING ucWindowName)
|
||||||
{
|
{
|
||||||
PWINDOW_OBJECT Parent, ChildAfter;
|
PWINDOW_OBJECT Parent, ChildAfter;
|
||||||
UNICODE_STRING ClassName, WindowName;
|
UNICODE_STRING ClassName = {0}, WindowName = {0};
|
||||||
NTSTATUS Status;
|
|
||||||
HWND Desktop, Ret = NULL;
|
HWND Desktop, Ret = NULL;
|
||||||
RTL_ATOM ClassAtom;
|
RTL_ATOM ClassAtom = (RTL_ATOM)0;
|
||||||
DECLARE_RETURN(HWND);
|
DECLARE_RETURN(HWND);
|
||||||
|
|
||||||
DPRINT("Enter NtUserFindWindowEx\n");
|
DPRINT("Enter NtUserFindWindowEx\n");
|
||||||
UserEnterShared();
|
UserEnterShared();
|
||||||
|
|
||||||
|
_SEH_TRY
|
||||||
|
{
|
||||||
|
if (ucClassName != NULL)
|
||||||
|
{
|
||||||
|
ClassName = ProbeForReadUnicodeString(ucClassName);
|
||||||
|
if (ClassName.Length != 0)
|
||||||
|
{
|
||||||
|
ProbeForRead(ClassName.Buffer,
|
||||||
|
ClassName.Length,
|
||||||
|
sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
else if (IS_ATOM(ClassName.Buffer))
|
||||||
|
{
|
||||||
|
if (!IntGetAtomFromStringOrAtom(&ClassName,
|
||||||
|
&ClassAtom))
|
||||||
|
{
|
||||||
|
_SEH_LEAVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ucWindowName != NULL)
|
||||||
|
{
|
||||||
|
WindowName = ProbeForReadUnicodeString(ucWindowName);
|
||||||
|
if (WindowName.Length != 0)
|
||||||
|
{
|
||||||
|
ProbeForRead(WindowName.Buffer,
|
||||||
|
WindowName.Length,
|
||||||
|
sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH_HANDLE
|
||||||
|
{
|
||||||
|
SetLastNtError(_SEH_GetExceptionCode());
|
||||||
|
RETURN(NULL);
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
|
||||||
|
if (ucClassName != NULL && ClassName.Length == 0)
|
||||||
|
{
|
||||||
|
if (!IS_ATOM(ClassName.Buffer))
|
||||||
|
{
|
||||||
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||||
|
RETURN(NULL);
|
||||||
|
}
|
||||||
|
else if (ClassAtom == (RTL_ATOM)0)
|
||||||
|
{
|
||||||
|
/* LastError code was set by IntGetAtomFromStringOrAtom */
|
||||||
|
RETURN(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Desktop = IntGetCurrentThreadDesktopWindow();
|
Desktop = IntGetCurrentThreadDesktopWindow();
|
||||||
|
|
||||||
if(hwndParent == NULL)
|
if(hwndParent == NULL)
|
||||||
|
@ -2456,158 +2508,91 @@ NtUserFindWindowEx(HWND hwndParent,
|
||||||
RETURN( NULL);
|
RETURN( NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the window name */
|
_SEH_TRY
|
||||||
Status = IntSafeCopyUnicodeString(&WindowName, ucWindowName);
|
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
SetLastNtError(Status);
|
if(Parent->hSelf == Desktop)
|
||||||
goto Cleanup3;
|
{
|
||||||
}
|
HWND *List, *phWnd;
|
||||||
|
PWINDOW_OBJECT TopLevelWindow;
|
||||||
|
BOOLEAN CheckWindowName;
|
||||||
|
BOOLEAN WindowMatches;
|
||||||
|
BOOLEAN ClassMatches;
|
||||||
|
|
||||||
/* safely copy the class name */
|
/* windows searches through all top-level windows if the parent is the desktop
|
||||||
Status = MmCopyFromCaller(&ClassName, ucClassName, sizeof(UNICODE_STRING));
|
window */
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
SetLastNtError(Status);
|
|
||||||
goto Cleanup2;
|
|
||||||
}
|
|
||||||
if(ClassName.Length > 0 && ClassName.Buffer)
|
|
||||||
{
|
|
||||||
WCHAR *buf;
|
|
||||||
/* safely copy the class name string (NULL terminated because class-lookup
|
|
||||||
depends on it... */
|
|
||||||
buf = ExAllocatePoolWithTag(PagedPool, ClassName.Length + sizeof(WCHAR), TAG_STRING);
|
|
||||||
if(!buf)
|
|
||||||
{
|
|
||||||
SetLastWin32Error(STATUS_INSUFFICIENT_RESOURCES);
|
|
||||||
goto Cleanup2;
|
|
||||||
}
|
|
||||||
Status = MmCopyFromCaller(buf, ClassName.Buffer, ClassName.Length);
|
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ExFreePool(buf);
|
|
||||||
SetLastNtError(Status);
|
|
||||||
goto Cleanup2;
|
|
||||||
}
|
|
||||||
ClassName.Buffer = buf;
|
|
||||||
/* make sure the string is null-terminated */
|
|
||||||
buf += ClassName.Length / sizeof(WCHAR);
|
|
||||||
*buf = L'\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the class object */
|
if((List = IntWinListChildren(Parent)))
|
||||||
if(ClassName.Buffer)
|
{
|
||||||
{
|
phWnd = List;
|
||||||
PWINSTATION_OBJECT WinStaObject;
|
|
||||||
|
|
||||||
if (PsGetWin32Thread()->Desktop == NULL)
|
if(ChildAfter)
|
||||||
{
|
{
|
||||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
/* skip handles before and including ChildAfter */
|
||||||
goto Cleanup;
|
while(*phWnd && (*(phWnd++) != ChildAfter->hSelf))
|
||||||
}
|
;
|
||||||
|
}
|
||||||
|
|
||||||
WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
|
CheckWindowName = WindowName.Length != 0;
|
||||||
|
|
||||||
Status = RtlLookupAtomInAtomTable(
|
/* search children */
|
||||||
WinStaObject->AtomTable,
|
while(*phWnd)
|
||||||
ClassName.Buffer,
|
{
|
||||||
&ClassAtom);
|
if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
/* Do not send WM_GETTEXT messages in the kernel mode version!
|
||||||
{
|
The user mode version however calls GetWindowText() which will
|
||||||
DPRINT1("Failed to lookup class atom!\n");
|
send WM_GETTEXT messages to windows belonging to its processes */
|
||||||
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
|
WindowMatches = !CheckWindowName || !RtlCompareUnicodeString(
|
||||||
goto Cleanup;
|
&WindowName, &TopLevelWindow->WindowName, TRUE);
|
||||||
}
|
ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
|
||||||
}
|
ClassAtom == TopLevelWindow->Class->Atom;
|
||||||
|
|
||||||
if(Parent->hSelf == Desktop)
|
if (WindowMatches && ClassMatches)
|
||||||
{
|
{
|
||||||
HWND *List, *phWnd;
|
Ret = TopLevelWindow->hSelf;
|
||||||
PWINDOW_OBJECT TopLevelWindow;
|
break;
|
||||||
BOOLEAN CheckWindowName;
|
}
|
||||||
BOOLEAN CheckClassName;
|
|
||||||
BOOLEAN WindowMatches;
|
|
||||||
BOOLEAN ClassMatches;
|
|
||||||
|
|
||||||
/* windows searches through all top-level windows if the parent is the desktop
|
if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
|
||||||
window */
|
{
|
||||||
|
/* window returns the handle of the top-level window, in case it found
|
||||||
|
the child window */
|
||||||
|
Ret = TopLevelWindow->hSelf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if((List = IntWinListChildren(Parent)))
|
}
|
||||||
{
|
ExFreePool(List);
|
||||||
phWnd = List;
|
}
|
||||||
|
}
|
||||||
if(ChildAfter)
|
else
|
||||||
{
|
Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
|
||||||
/* skip handles before and including ChildAfter */
|
|
||||||
while(*phWnd && (*(phWnd++) != ChildAfter->hSelf))
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckWindowName = WindowName.Length > 0;
|
|
||||||
CheckClassName = ClassName.Buffer != NULL;
|
|
||||||
|
|
||||||
/* search children */
|
|
||||||
while(*phWnd)
|
|
||||||
{
|
|
||||||
if(!(TopLevelWindow = UserGetWindowObject(*(phWnd++))))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do not send WM_GETTEXT messages in the kernel mode version!
|
|
||||||
The user mode version however calls GetWindowText() which will
|
|
||||||
send WM_GETTEXT messages to windows belonging to its processes */
|
|
||||||
WindowMatches = !CheckWindowName || !RtlCompareUnicodeString(
|
|
||||||
&WindowName, &TopLevelWindow->WindowName, TRUE);
|
|
||||||
ClassMatches = !CheckClassName ||
|
|
||||||
ClassAtom == TopLevelWindow->Class->Atom;
|
|
||||||
|
|
||||||
if (WindowMatches && ClassMatches)
|
|
||||||
{
|
|
||||||
Ret = TopLevelWindow->hSelf;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IntFindWindow(TopLevelWindow, NULL, ClassAtom, &WindowName))
|
|
||||||
{
|
|
||||||
/* window returns the handle of the top-level window, in case it found
|
|
||||||
the child window */
|
|
||||||
Ret = TopLevelWindow->hSelf;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
ExFreePool(List);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
if(Ret == NULL && hwndParent == NULL && hwndChildAfter == NULL)
|
if(Ret == NULL && hwndParent == NULL && hwndChildAfter == NULL)
|
||||||
{
|
{
|
||||||
/* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
|
/* FIXME - if both hwndParent and hwndChildAfter are NULL, we also should
|
||||||
search the message-only windows. Should this also be done if
|
search the message-only windows. Should this also be done if
|
||||||
Parent is the desktop window??? */
|
Parent is the desktop window??? */
|
||||||
PWINDOW_OBJECT MsgWindows;
|
PWINDOW_OBJECT MsgWindows;
|
||||||
|
|
||||||
if((MsgWindows = UserGetWindowObject(IntGetMessageWindow())))
|
if((MsgWindows = UserGetWindowObject(IntGetMessageWindow())))
|
||||||
{
|
{
|
||||||
Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
|
Ret = IntFindWindow(MsgWindows, ChildAfter, ClassAtom, &WindowName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
Cleanup:
|
_SEH_HANDLE
|
||||||
if(ClassName.Length > 0 && ClassName.Buffer)
|
{
|
||||||
ExFreePool(ClassName.Buffer);
|
SetLastNtError(_SEH_GetExceptionCode());
|
||||||
|
Ret = NULL;
|
||||||
Cleanup2:
|
}
|
||||||
RtlFreeUnicodeString(&WindowName);
|
_SEH_END;
|
||||||
|
|
||||||
Cleanup3:
|
|
||||||
|
|
||||||
RETURN( Ret);
|
RETURN( Ret);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue