[NTUSER][USER32] Make NtUserBuildHwndList exclusive (#4485)

- Modify prototype of NtUserBuildHwndList function.
- Wrap the code by UserEnterExclusive(); and UserLeave();.
CORE-18173
This commit is contained in:
Katayama Hirofumi MZ 2022-05-05 08:49:00 +09:00 committed by GitHub
parent bbc9a877cc
commit c2a51c7249
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 28 deletions

View file

@ -1561,9 +1561,9 @@ NtUserBuildHwndList(
HWND hwndParent, HWND hwndParent,
BOOLEAN bChildren, BOOLEAN bChildren,
ULONG dwThreadId, ULONG dwThreadId,
ULONG lParam, ULONG cHwnd,
HWND *pWnd, HWND *phwndList,
ULONG *pBufSize); ULONG *pcHwndNeeded);
NTSTATUS NTSTATUS
NTAPI NTAPI

View file

@ -1500,22 +1500,24 @@ VOID FASTCALL IntFreeHwndList(PWINDOWLIST pwlTarget)
* @implemented * @implemented
*/ */
NTSTATUS NTSTATUS
APIENTRY NTAPI
NtUserBuildHwndList( NtUserBuildHwndList(
HDESK hDesktop, HDESK hDesktop,
HWND hwndParent, HWND hwndParent,
BOOLEAN bChildren, BOOLEAN bChildren,
ULONG dwThreadId, ULONG dwThreadId,
ULONG lParam, ULONG cHwnd,
HWND* pWnd, HWND* phwndList,
ULONG* pBufSize) ULONG* pcHwndNeeded)
{ {
NTSTATUS Status; NTSTATUS Status;
ULONG dwCount = 0; ULONG dwCount = 0;
if (pBufSize == 0) if (pcHwndNeeded == NULL)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
UserEnterExclusive();
if (hwndParent || !dwThreadId) if (hwndParent || !dwThreadId)
{ {
PDESKTOP Desktop; PDESKTOP Desktop;
@ -1525,7 +1527,8 @@ NtUserBuildHwndList(
{ {
if(hDesktop == NULL && !(Desktop = IntGetActiveDesktop())) if(hDesktop == NULL && !(Desktop = IntGetActiveDesktop()))
{ {
return ERROR_INVALID_HANDLE; Status = ERROR_INVALID_HANDLE;
goto Quit;
} }
if(hDesktop) if(hDesktop)
@ -1536,7 +1539,8 @@ NtUserBuildHwndList(
&Desktop); &Desktop);
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
return ERROR_INVALID_HANDLE; Status = ERROR_INVALID_HANDLE;
goto Quit;
} }
} }
hwndParent = Desktop->DesktopWindow; hwndParent = Desktop->DesktopWindow;
@ -1556,13 +1560,13 @@ NtUserBuildHwndList(
{ {
if (bGoDown) if (bGoDown)
{ {
if(dwCount++ < *pBufSize && pWnd) if (dwCount++ < cHwnd && phwndList)
{ {
_SEH2_TRY _SEH2_TRY
{ {
ProbeForWrite(pWnd, sizeof(HWND), 1); ProbeForWrite(phwndList, sizeof(HWND), 1);
*pWnd = Window->head.h; *phwndList = Window->head.h;
pWnd++; phwndList++;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -1571,7 +1575,6 @@ NtUserBuildHwndList(
_SEH2_END _SEH2_END
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
SetLastNtError(Status);
break; break;
} }
} }
@ -1612,13 +1615,15 @@ NtUserBuildHwndList(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ERR("Thread Id is not valid!\n"); ERR("Thread Id is not valid!\n");
return ERROR_INVALID_PARAMETER; Status = ERROR_INVALID_PARAMETER;
goto Quit;
} }
if (!(W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread)) if (!(W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread))
{ {
ObDereferenceObject(Thread); ObDereferenceObject(Thread);
TRACE("Tried to enumerate windows of a non gui thread\n"); TRACE("Tried to enumerate windows of a non gui thread\n");
return ERROR_INVALID_PARAMETER; Status = ERROR_INVALID_PARAMETER;
goto Quit;
} }
// Do not use Thread link list due to co_UserFreeWindow!!! // Do not use Thread link list due to co_UserFreeWindow!!!
@ -1633,13 +1638,13 @@ NtUserBuildHwndList(
Window = ValidateHwndNoErr(List[i]); Window = ValidateHwndNoErr(List[i]);
if (Window && Window->head.pti == W32Thread) if (Window && Window->head.pti == W32Thread)
{ {
if (dwCount < *pBufSize && pWnd) if (dwCount < cHwnd && phwndList)
{ {
_SEH2_TRY _SEH2_TRY
{ {
ProbeForWrite(pWnd, sizeof(HWND), 1); ProbeForWrite(phwndList, sizeof(HWND), 1);
*pWnd = Window->head.h; *phwndList = Window->head.h;
pWnd++; phwndList++;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -1649,7 +1654,6 @@ NtUserBuildHwndList(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ERR("Failure to build window list!\n"); ERR("Failure to build window list!\n");
SetLastNtError(Status);
break; break;
} }
} }
@ -1662,8 +1666,13 @@ NtUserBuildHwndList(
ObDereferenceObject(Thread); ObDereferenceObject(Thread);
} }
*pBufSize = dwCount; *pcHwndNeeded = dwCount;
return STATUS_SUCCESS; Status = STATUS_SUCCESS;
Quit:
SetLastNtError(Status);
UserLeave();
return Status;
} }
static void IntSendParentNotify( PWND pWindow, UINT msg ) static void IntSendParentNotify( PWND pWindow, UINT msg )

View file

@ -145,7 +145,7 @@ HWND* WIN_ListChildren (HWND hWndparent)
HANDLE hHeap; HANDLE hHeap;
NTSTATUS Status; NTSTATUS Status;
Status = NtUserBuildHwndList ( NULL, hWndparent, FALSE, 0, 0, NULL, &dwCount ); Status = NtUserBuildHwndList(NULL, hWndparent, FALSE, 0, dwCount, NULL, &dwCount);
if ( !NT_SUCCESS( Status ) ) if ( !NT_SUCCESS( Status ) )
return 0; return 0;
@ -161,7 +161,7 @@ HWND* WIN_ListChildren (HWND hWndparent)
} }
/* now call kernel again to fill the buffer this time */ /* now call kernel again to fill the buffer this time */
Status = NtUserBuildHwndList (NULL, hWndparent, FALSE, 0, 0, pHwnd, &dwCount ); Status = NtUserBuildHwndList(NULL, hWndparent, FALSE, 0, dwCount, pHwnd, &dwCount);
if ( !NT_SUCCESS( Status ) ) if ( !NT_SUCCESS( Status ) )
{ {

View file

@ -701,7 +701,7 @@ User32EnumWindows(HDESK hDesktop,
hWndparent, hWndparent,
bChildren, bChildren,
dwThreadId, dwThreadId,
lParam, dwCount,
NULL, NULL,
&dwCount); &dwCount);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -729,7 +729,7 @@ User32EnumWindows(HDESK hDesktop,
hWndparent, hWndparent,
bChildren, bChildren,
dwThreadId, dwThreadId,
lParam, dwCount,
pHwnd, pHwnd,
&dwCount); &dwCount);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))