mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 09:46:18 +00:00
[WIN32SS:NTUSER] Use the 2nd parameter of NtUserGetThreadDesktop() as fallback. (#1065)
- The 2nd parameter is already passed in user-mode by GetThreadDesktop(). It is then used by NtUserGetThreadDesktop() as a fallback for console threads. - Lookup and validate the thread by using the IntTID2PTI() helper. - Don't reference the desktop with too many access rights. - Get rid of the old-school DECLARE_RETURN() & co. macros. Co-authored-by: Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
This commit is contained in:
parent
23ad2173f2
commit
458a26ab76
3 changed files with 76 additions and 46 deletions
|
@ -2439,7 +2439,7 @@ HDESK
|
||||||
NTAPI
|
NTAPI
|
||||||
NtUserGetThreadDesktop(
|
NtUserGetThreadDesktop(
|
||||||
DWORD dwThreadId,
|
DWORD dwThreadId,
|
||||||
DWORD Unknown1);
|
HDESK hConsoleDesktop);
|
||||||
|
|
||||||
enum ThreadStateRoutines
|
enum ThreadStateRoutines
|
||||||
{
|
{
|
||||||
|
|
|
@ -2981,14 +2981,14 @@ CLEANUP:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HDESK APIENTRY
|
HDESK APIENTRY
|
||||||
NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
|
NtUserGetThreadDesktop(DWORD dwThreadId, HDESK hConsoleDesktop)
|
||||||
{
|
{
|
||||||
|
HDESK hDesk;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PETHREAD Thread;
|
PTHREADINFO pti;
|
||||||
|
PEPROCESS Process;
|
||||||
PDESKTOP DesktopObject;
|
PDESKTOP DesktopObject;
|
||||||
HDESK hDesk, hThreadDesktop;
|
|
||||||
OBJECT_HANDLE_INFORMATION HandleInformation;
|
OBJECT_HANDLE_INFORMATION HandleInformation;
|
||||||
DECLARE_RETURN(HDESK);
|
|
||||||
|
|
||||||
UserEnterExclusive();
|
UserEnterExclusive();
|
||||||
TRACE("Enter NtUserGetThreadDesktop\n");
|
TRACE("Enter NtUserGetThreadDesktop\n");
|
||||||
|
@ -2996,67 +2996,97 @@ NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
|
||||||
if (!dwThreadId)
|
if (!dwThreadId)
|
||||||
{
|
{
|
||||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
RETURN(0);
|
hDesk = NULL;
|
||||||
|
goto Quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &Thread);
|
/* Validate the Win32 thread and retrieve its information */
|
||||||
if (!NT_SUCCESS(Status))
|
pti = IntTID2PTI(UlongToHandle(dwThreadId));
|
||||||
|
if (pti)
|
||||||
|
{
|
||||||
|
/* Get the desktop handle of the thread */
|
||||||
|
hDesk = pti->hdesk;
|
||||||
|
Process = pti->ppi->peProcess;
|
||||||
|
}
|
||||||
|
else if (hConsoleDesktop)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The thread may belong to a console, so attempt to use the provided
|
||||||
|
* console desktop handle as a fallback. Otherwise this means that the
|
||||||
|
* thread is either not Win32 or invalid.
|
||||||
|
*/
|
||||||
|
hDesk = hConsoleDesktop;
|
||||||
|
Process = gpepCSRSS;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
RETURN(0);
|
hDesk = NULL;
|
||||||
|
goto Quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Thread->ThreadsProcess == PsGetCurrentProcess())
|
if (!hDesk)
|
||||||
{
|
{
|
||||||
/* Just return the handle, we queried the desktop handle of a thread running
|
|
||||||
in the same context */
|
|
||||||
hDesk = ((PTHREADINFO)Thread->Tcb.Win32Thread)->hdesk;
|
|
||||||
ObDereferenceObject(Thread);
|
|
||||||
RETURN(hDesk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the desktop handle and the desktop of the thread */
|
|
||||||
if (!(hThreadDesktop = ((PTHREADINFO)Thread->Tcb.Win32Thread)->hdesk) ||
|
|
||||||
!(DesktopObject = ((PTHREADINFO)Thread->Tcb.Win32Thread)->rpdesk))
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Thread);
|
|
||||||
ERR("Desktop information of thread 0x%x broken!?\n", dwThreadId);
|
ERR("Desktop information of thread 0x%x broken!?\n", dwThreadId);
|
||||||
RETURN(NULL);
|
goto Quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We could just use DesktopObject instead of looking up the handle, but latter
|
if (Process == PsGetCurrentProcess())
|
||||||
may be a bit safer (e.g. when the desktop is being destroyed */
|
{
|
||||||
/* Switch into the context of the thread we're trying to get the desktop from,
|
/*
|
||||||
so we can use the handle */
|
* Just return the handle, since we queried the desktop handle
|
||||||
KeAttachProcess(&Thread->ThreadsProcess->Pcb);
|
* of a thread running in the same context.
|
||||||
Status = ObReferenceObjectByHandle(hThreadDesktop,
|
*/
|
||||||
GENERIC_ALL,
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We could just use the cached rpdesk instead of looking up the handle,
|
||||||
|
* but it may actually be safer to validate the desktop and get a temporary
|
||||||
|
* reference to it so that it does not disappear under us (e.g. when the
|
||||||
|
* desktop is being destroyed) during the operation.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Switch into the context of the thread we are trying to get
|
||||||
|
* the desktop from, so we can use the handle.
|
||||||
|
*/
|
||||||
|
KeAttachProcess(&Process->Pcb);
|
||||||
|
Status = ObReferenceObjectByHandle(hDesk,
|
||||||
|
0,
|
||||||
ExDesktopObjectType,
|
ExDesktopObjectType,
|
||||||
UserMode,
|
UserMode,
|
||||||
(PVOID*)&DesktopObject,
|
(PVOID*)&DesktopObject,
|
||||||
&HandleInformation);
|
&HandleInformation);
|
||||||
KeDetachProcess();
|
KeDetachProcess();
|
||||||
|
|
||||||
/* The handle couldn't be found, there's nothing to get... */
|
if (NT_SUCCESS(Status))
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
ObDereferenceObject(Thread);
|
/*
|
||||||
RETURN(NULL);
|
* Lookup our handle table if we can find a handle to the desktop object.
|
||||||
}
|
* If not, create one.
|
||||||
|
* QUESTION: Do we really need to create a handle in case it doesn't exist??
|
||||||
/* Lookup our handle table if we can find a handle to the desktop object,
|
*/
|
||||||
if not, create one */
|
|
||||||
hDesk = IntGetDesktopObjectHandle(DesktopObject);
|
hDesk = IntGetDesktopObjectHandle(DesktopObject);
|
||||||
|
|
||||||
/* All done, we got a valid handle to the desktop */
|
/* All done, we got a valid handle to the desktop */
|
||||||
ObDereferenceObject(DesktopObject);
|
ObDereferenceObject(DesktopObject);
|
||||||
ObDereferenceObject(Thread);
|
}
|
||||||
RETURN(hDesk);
|
else
|
||||||
|
{
|
||||||
|
/* The handle could not be found, there is nothing to get... */
|
||||||
|
hDesk = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
CLEANUP:
|
if (!hDesk)
|
||||||
TRACE("Leave NtUserGetThreadDesktop, ret=%p\n",_ret_);
|
{
|
||||||
|
ERR("Could not retrieve or access desktop for thread 0x%x\n", dwThreadId);
|
||||||
|
EngSetLastError(ERROR_ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
TRACE("Leave NtUserGetThreadDesktop, hDesk = 0x%p\n", hDesk);
|
||||||
UserLeave();
|
UserLeave();
|
||||||
END_CLEANUP;
|
return hDesk;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
|
|
|
@ -563,7 +563,7 @@ GetThreadDesktop(
|
||||||
}
|
}
|
||||||
|
|
||||||
return NtUserGetThreadDesktop(dwThreadId,
|
return NtUserGetThreadDesktop(dwThreadId,
|
||||||
(DWORD_PTR)GetThreadConsoleDesktopRequest->ConsoleDesktop);
|
GetThreadConsoleDesktopRequest->ConsoleDesktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue