mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
[WIN32K:NTUSER] Make NtUserResolveDesktop() and IntResolveDesktop() work in a more Win2k3-compatible manner.
CORE-11933 and PR #621. Since this API is also called from WINSRV when calling the AllocConsole() API, it can be tested more-or-less easily. The internal helper IntResolveDesktop() is also tested during process connection to a window station, when such process first calls a USER32 or GDI32 function. This is also the functionality tested by the user32:desktop apitest. - Adjust how IntResolveDesktop() is called.
This commit is contained in:
parent
83104d9f00
commit
c697f191cf
|
@ -2912,11 +2912,11 @@ NtUserRemoveProp(
|
||||||
ATOM Atom);
|
ATOM Atom);
|
||||||
|
|
||||||
HDESK
|
HDESK
|
||||||
APIENTRY
|
NTAPI
|
||||||
NtUserResolveDesktop(
|
NtUserResolveDesktop(
|
||||||
IN HANDLE ProcessHandle,
|
IN HANDLE ProcessHandle,
|
||||||
IN PUNICODE_STRING DesktopPath,
|
IN PUNICODE_STRING DesktopPath,
|
||||||
DWORD dwUnknown,
|
IN BOOL bInherit,
|
||||||
OUT HWINSTA* phWinSta);
|
OUT HWINSTA* phWinSta);
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
|
|
|
@ -447,139 +447,726 @@ GetSystemVersionString(OUT PWSTR pwszzVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
/*
|
||||||
IntParseDesktopPath(PEPROCESS Process,
|
* IntResolveDesktop
|
||||||
PUNICODE_STRING DesktopPath,
|
*
|
||||||
HWINSTA *hWinSta,
|
* The IntResolveDesktop function attempts to retrieve valid handles to
|
||||||
HDESK *hDesktop)
|
* a desktop and a window station suitable for the specified process.
|
||||||
{
|
* The specified desktop path string is used only as a hint for the resolution.
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
*
|
||||||
UNICODE_STRING ObjectName;
|
* - If the process is already assigned to a window station and a desktop,
|
||||||
NTSTATUS Status;
|
* handles to these objects are returned directly regardless of the specified
|
||||||
WCHAR wstrWinstaFullName[MAX_PATH], *pwstrWinsta = NULL, *pwstrDesktop = NULL;
|
* desktop path string. This is what happens when this function is called for
|
||||||
|
* a process that has been already started and connected to the Win32 USER.
|
||||||
|
*
|
||||||
|
* - If the process is being connected to the Win32 USER, or is in a state
|
||||||
|
* where a window station is assigned to it but no desktop yet, the desktop
|
||||||
|
* path string is used as a hint for the resolution.
|
||||||
|
* A specified window station (if any, otherwise "WinSta0" is used as default)
|
||||||
|
* is tested for existence and accessibility. If the checks are OK a handle
|
||||||
|
* to it is returned. Otherwise we either fail (the window station does not
|
||||||
|
* exist) or, in case a default window station was used, we attempt to open
|
||||||
|
* or create a non-interactive Service-0xXXXX-YYYY$ window station. This is
|
||||||
|
* typically what happens when a non-interactive process is started while
|
||||||
|
* the WinSta0 window station was used as the default one.
|
||||||
|
* A specified desktop (if any, otherwise "Default" is used as default)
|
||||||
|
* is then tested for existence on the opened window station.
|
||||||
|
*
|
||||||
|
* - Rules for the choice of the default window station, when none is specified
|
||||||
|
* in the desktop path:
|
||||||
|
*
|
||||||
|
* 1. By default, a SYSTEM process connects to a non-interactive window
|
||||||
|
* station, either the Service-0x0-3e7$ (from the SYSTEM LUID) station,
|
||||||
|
* or one that has been inherited and that is non-interactive.
|
||||||
|
* Only when the interactive window station WinSta0 is specified that
|
||||||
|
* the process can connect to it (e.g. the case of interactive services).
|
||||||
|
*
|
||||||
|
* 2. An interactive process, i.e. a process whose LUID is the same as the
|
||||||
|
* one assigned to WinSta0 by Winlogon on user logon, connects by default
|
||||||
|
* to the WinSta0 window station, unless it has inherited from another
|
||||||
|
* interactive window station (which must be... none other than WinSta0).
|
||||||
|
*
|
||||||
|
* 3. A non-interactive (but not SYSTEM) process connects by default to
|
||||||
|
* a non-interactive Service-0xXXXX-YYYY$ window station (whose name
|
||||||
|
* is derived from the process' LUID), or to another non-interactive
|
||||||
|
* window station that has been inherited.
|
||||||
|
* Otherwise it may be able connect to the interactive WinSta0 only if
|
||||||
|
* it has explicit access rights to it.
|
||||||
|
*
|
||||||
|
* Parameters
|
||||||
|
* Process
|
||||||
|
* The user process object.
|
||||||
|
*
|
||||||
|
* DesktopPath
|
||||||
|
* The desktop path string used as a hint for desktop resolution.
|
||||||
|
*
|
||||||
|
* bInherit
|
||||||
|
* Whether or not the returned handles are inheritable.
|
||||||
|
*
|
||||||
|
* phWinSta
|
||||||
|
* Pointer to a window station handle.
|
||||||
|
*
|
||||||
|
* phDesktop
|
||||||
|
* Pointer to a desktop handle.
|
||||||
|
*
|
||||||
|
* Return Value
|
||||||
|
* Status code.
|
||||||
|
*/
|
||||||
|
|
||||||
ASSERT(hWinSta);
|
NTSTATUS
|
||||||
ASSERT(hDesktop);
|
FASTCALL
|
||||||
|
IntResolveDesktop(
|
||||||
|
IN PEPROCESS Process,
|
||||||
|
IN PUNICODE_STRING DesktopPath,
|
||||||
|
IN BOOL bInherit,
|
||||||
|
OUT HWINSTA* phWinSta,
|
||||||
|
OUT HDESK* phDesktop)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HWINSTA hWinSta = NULL, hWinStaDup = NULL;
|
||||||
|
HDESK hDesktop = NULL, hDesktopDup = NULL;
|
||||||
|
PPROCESSINFO ppi;
|
||||||
|
HANDLE hProcess = NULL;
|
||||||
|
LUID ProcessLuid;
|
||||||
|
USHORT StrSize;
|
||||||
|
SIZE_T MemSize;
|
||||||
|
POBJECT_ATTRIBUTES ObjectAttributes = NULL;
|
||||||
|
PUNICODE_STRING ObjectName;
|
||||||
|
UNICODE_STRING WinStaName, DesktopName;
|
||||||
|
const UNICODE_STRING WinSta0Name = RTL_CONSTANT_STRING(L"WinSta0");
|
||||||
|
PWINSTATION_OBJECT WinStaObject;
|
||||||
|
HWINSTA hTempWinSta = NULL;
|
||||||
|
BOOLEAN bUseDefaultWinSta = FALSE;
|
||||||
|
BOOLEAN bInteractive = FALSE;
|
||||||
|
BOOLEAN bAccessAllowed = FALSE;
|
||||||
|
|
||||||
|
ASSERT(phWinSta);
|
||||||
|
ASSERT(phDesktop);
|
||||||
ASSERT(DesktopPath);
|
ASSERT(DesktopPath);
|
||||||
|
|
||||||
*hWinSta = NULL;
|
*phWinSta = NULL;
|
||||||
*hDesktop = NULL;
|
*phDesktop = NULL;
|
||||||
|
|
||||||
if (DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
|
ppi = PsGetProcessWin32Process(Process);
|
||||||
|
/* ppi is typically NULL for console applications that connect to Win32 USER */
|
||||||
|
if (!ppi) TRACE("IntResolveDesktop: ppi is NULL!\n");
|
||||||
|
|
||||||
|
if (ppi && ppi->hwinsta != NULL && ppi->hdeskStartup != NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Parse the desktop path string which can be in the form "WinSta\Desktop"
|
* If this process is the current one, just return the cached handles.
|
||||||
* or just "Desktop". In latter case WinSta0 will be used.
|
* Otherwise, open the window station and desktop objects.
|
||||||
*/
|
*/
|
||||||
|
if (Process == PsGetCurrentProcess())
|
||||||
pwstrDesktop = wcschr(DesktopPath->Buffer, L'\\');
|
|
||||||
if (pwstrDesktop != NULL)
|
|
||||||
{
|
{
|
||||||
*pwstrDesktop = 0;
|
hWinSta = ppi->hwinsta;
|
||||||
pwstrDesktop++;
|
hDesktop = ppi->hdeskStartup;
|
||||||
pwstrWinsta = DesktopPath->Buffer;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pwstrDesktop = DesktopPath->Buffer;
|
Status = ObOpenObjectByPointer(ppi->prpwinsta,
|
||||||
pwstrWinsta = NULL;
|
0,
|
||||||
|
NULL,
|
||||||
|
MAXIMUM_ALLOWED,
|
||||||
|
ExWindowStationObjectType,
|
||||||
|
UserMode,
|
||||||
|
(PHANDLE)&hWinSta);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("IntResolveDesktop: Could not reference window station 0x%p\n", ppi->prpwinsta);
|
||||||
|
SetLastNtError(Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ObOpenObjectByPointer(ppi->rpdeskStartup,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
MAXIMUM_ALLOWED,
|
||||||
|
ExDesktopObjectType,
|
||||||
|
UserMode,
|
||||||
|
(PHANDLE)&hDesktop);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("IntResolveDesktop: Could not reference desktop 0x%p\n", ppi->rpdeskStartup);
|
||||||
|
ObCloseHandle(hWinSta, UserMode);
|
||||||
|
SetLastNtError(Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("IntParseDesktopPath pwstrWinsta:%S pwstrDesktop:%S\n", pwstrWinsta, pwstrDesktop);
|
*phWinSta = hWinSta;
|
||||||
|
*phDesktop = hDesktop;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
/* We will by default use the default window station and desktop */
|
||||||
/* Search the process handle table for (inherited) window station
|
RtlInitEmptyUnicodeString(&WinStaName, NULL, 0);
|
||||||
handles, use a more appropriate one than WinSta0 if possible. */
|
RtlInitEmptyUnicodeString(&DesktopName, NULL, 0);
|
||||||
if (!ObFindHandleForObject(Process,
|
|
||||||
NULL,
|
/*
|
||||||
ExWindowStationObjectType,
|
* Parse the desktop path string which can be of the form "WinSta\Desktop"
|
||||||
NULL,
|
* or just "Desktop". In the latter case we use the default window station
|
||||||
(PHANDLE)hWinSta))
|
* on which the process is attached to (or if none, "WinSta0").
|
||||||
#endif
|
*/
|
||||||
|
if (DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
|
||||||
{
|
{
|
||||||
/* We had no luck searching for opened handles, use WinSta0 now */
|
DesktopName = *DesktopPath;
|
||||||
if (!pwstrWinsta)
|
|
||||||
pwstrWinsta = L"WinSta0";
|
/* Find the separator */
|
||||||
|
while (DesktopName.Length > 0 && *DesktopName.Buffer &&
|
||||||
|
*DesktopName.Buffer != OBJ_NAME_PATH_SEPARATOR)
|
||||||
|
{
|
||||||
|
DesktopName.Buffer++;
|
||||||
|
DesktopName.Length -= sizeof(WCHAR);
|
||||||
|
DesktopName.MaximumLength -= sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
if (DesktopName.Length > 0)
|
||||||
|
{
|
||||||
|
RtlInitEmptyUnicodeString(&WinStaName, DesktopPath->Buffer,
|
||||||
|
DesktopPath->Length - DesktopName.Length);
|
||||||
|
// (USHORT)((ULONG_PTR)DesktopName.Buffer - (ULONG_PTR)DesktopPath->Buffer);
|
||||||
|
WinStaName.Length = WinStaName.MaximumLength;
|
||||||
|
|
||||||
|
/* Skip the separator */
|
||||||
|
DesktopName.Buffer++;
|
||||||
|
DesktopName.Length -= sizeof(WCHAR);
|
||||||
|
DesktopName.MaximumLength -= sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlInitEmptyUnicodeString(&WinStaName, NULL, 0);
|
||||||
|
DesktopName = *DesktopPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
TRACE("IntResolveDesktop: WinStaName:'%wZ' ; DesktopName:'%wZ'\n", &WinStaName, &DesktopName);
|
||||||
/* Search the process handle table for (inherited) desktop
|
|
||||||
handles, use a more appropriate one than Default if possible. */
|
/* Retrieve the process LUID */
|
||||||
if (!ObFindHandleForObject(Process,
|
Status = GetProcessLuid(NULL, Process, &ProcessLuid);
|
||||||
NULL,
|
if (!NT_SUCCESS(Status))
|
||||||
ExDesktopObjectType,
|
|
||||||
NULL,
|
|
||||||
(PHANDLE)hDesktop))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
/* We had no luck searching for opened handles, use Desktop now */
|
ERR("IntResolveDesktop: Failed to retrieve the process LUID, Status 0x%08lx\n", Status);
|
||||||
if (!pwstrDesktop)
|
SetLastNtError(Status);
|
||||||
pwstrDesktop = L"Default";
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*hWinSta == NULL)
|
/*
|
||||||
|
* If this process is not the current one, obtain a temporary handle
|
||||||
|
* to it so that we can perform handles duplication later.
|
||||||
|
*/
|
||||||
|
if (Process != PsGetCurrentProcess())
|
||||||
{
|
{
|
||||||
swprintf(wstrWinstaFullName, L"%wZ\\%ws", &gustrWindowStationsDir, pwstrWinsta);
|
Status = ObOpenObjectByPointer(Process,
|
||||||
RtlInitUnicodeString( &ObjectName, wstrWinstaFullName);
|
OBJ_KERNEL_HANDLE,
|
||||||
|
NULL,
|
||||||
TRACE("parsed initial winsta: %wZ\n", &ObjectName);
|
0,
|
||||||
|
*PsProcessType,
|
||||||
/* Open the window station */
|
KernelMode,
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
&hProcess);
|
||||||
&ObjectName,
|
|
||||||
OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
Status = ObOpenObjectByName(&ObjectAttributes,
|
|
||||||
ExWindowStationObjectType,
|
|
||||||
KernelMode,
|
|
||||||
NULL,
|
|
||||||
WINSTA_ACCESS_ALL,
|
|
||||||
NULL,
|
|
||||||
(HANDLE*)hWinSta);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
ERR("IntResolveDesktop: Failed to obtain a handle to process 0x%p, Status 0x%08lx\n", Process, Status);
|
||||||
SetLastNtError(Status);
|
SetLastNtError(Status);
|
||||||
ERR("Failed to reference window station %wZ PID: --!\n", &ObjectName );
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
ASSERT(hProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no window station has been specified, search the process handle table
|
||||||
|
* for inherited window station handles, otherwise use a default one.
|
||||||
|
*/
|
||||||
|
if (WinStaName.Buffer == NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We want to find a suitable default window station.
|
||||||
|
* For applications that can be interactive, i.e. that have allowed
|
||||||
|
* access to the single interactive window station on the system,
|
||||||
|
* the default window station is 'WinSta0'.
|
||||||
|
* For applications that cannot be interactive, i.e. that do not have
|
||||||
|
* access to 'WinSta0' (e.g. non-interactive services), the default
|
||||||
|
* window station is 'Service-0xXXXX-YYYY$' (created if needed).
|
||||||
|
* Precedence will however be taken by any inherited window station
|
||||||
|
* that possesses the required interactivity property.
|
||||||
|
*/
|
||||||
|
bUseDefaultWinSta = TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the default 'WinSta0' window station. Whether we should
|
||||||
|
* use 'Service-0xXXXX-YYYY$' instead will be determined later.
|
||||||
|
*/
|
||||||
|
// RtlInitUnicodeString(&WinStaName, L"WinSta0");
|
||||||
|
WinStaName = WinSta0Name;
|
||||||
|
|
||||||
|
if (ObFindHandleForObject(Process,
|
||||||
|
NULL,
|
||||||
|
ExWindowStationObjectType,
|
||||||
|
NULL,
|
||||||
|
(PHANDLE)&hWinSta))
|
||||||
|
{
|
||||||
|
TRACE("IntResolveDesktop: Inherited window station is: 0x%p\n", hWinSta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*hDesktop == NULL)
|
/*
|
||||||
|
* If no desktop has been specified, search the process handle table
|
||||||
|
* for inherited desktop handles, otherwise use the Default desktop.
|
||||||
|
* Note that the inherited desktop that we may use, may not belong
|
||||||
|
* to the window station we will connect to.
|
||||||
|
*/
|
||||||
|
if (DesktopName.Buffer == NULL)
|
||||||
{
|
{
|
||||||
RtlInitUnicodeString(&ObjectName, pwstrDesktop);
|
/* Use a default desktop name */
|
||||||
|
RtlInitUnicodeString(&DesktopName, L"Default");
|
||||||
|
|
||||||
TRACE("parsed initial desktop: %wZ\n", &ObjectName);
|
if (ObFindHandleForObject(Process,
|
||||||
|
NULL,
|
||||||
|
ExDesktopObjectType,
|
||||||
|
NULL,
|
||||||
|
(PHANDLE)&hDesktop))
|
||||||
|
{
|
||||||
|
TRACE("IntResolveDesktop: Inherited desktop is: 0x%p\n", hDesktop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are going to open either a window station or a desktop.
|
||||||
|
* Even if this operation is done from kernel-mode, we should
|
||||||
|
* "emulate" an opening from user-mode (i.e. using an ObjectAttributes
|
||||||
|
* allocated in user-mode, with AccessMode == UserMode) for the
|
||||||
|
* Object Manager to perform proper access validation to the
|
||||||
|
* window station or desktop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Estimate the maximum size needed for the window station name
|
||||||
|
* and desktop name to be given to ObjectAttributes->ObjectName.
|
||||||
|
*/
|
||||||
|
StrSize = 0;
|
||||||
|
|
||||||
|
/* Window station name */
|
||||||
|
MemSize = _scwprintf(L"Service-0x%x-%x$", MAXULONG, MAXULONG) * sizeof(WCHAR);
|
||||||
|
MemSize = gustrWindowStationsDir.Length + sizeof(OBJ_NAME_PATH_SEPARATOR)
|
||||||
|
+ max(WinStaName.Length, MemSize) + sizeof(UNICODE_NULL);
|
||||||
|
if (MemSize > MAXUSHORT)
|
||||||
|
{
|
||||||
|
ERR("IntResolveDesktop: Window station name length is too long.\n");
|
||||||
|
Status = STATUS_NAME_TOO_LONG;
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
StrSize = max(StrSize, (USHORT)MemSize);
|
||||||
|
|
||||||
|
/* Desktop name */
|
||||||
|
MemSize = max(DesktopName.Length + sizeof(UNICODE_NULL), sizeof(L"Default"));
|
||||||
|
StrSize = max(StrSize, (USHORT)MemSize);
|
||||||
|
|
||||||
|
/* Size for the OBJECT_ATTRIBUTES */
|
||||||
|
MemSize = ALIGN_UP(sizeof(OBJECT_ATTRIBUTES), sizeof(PVOID));
|
||||||
|
|
||||||
|
/* Add the string size */
|
||||||
|
MemSize += ALIGN_UP(sizeof(UNICODE_STRING), sizeof(PVOID));
|
||||||
|
MemSize += StrSize;
|
||||||
|
|
||||||
|
/* Allocate the memory in user-mode */
|
||||||
|
Status = ZwAllocateVirtualMemory(ZwCurrentProcess(),
|
||||||
|
(PVOID*)&ObjectAttributes,
|
||||||
|
0,
|
||||||
|
&MemSize,
|
||||||
|
MEM_COMMIT,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("ZwAllocateVirtualMemory() failed, Status 0x%08lx\n", Status);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectName = (PUNICODE_STRING)((ULONG_PTR)ObjectAttributes +
|
||||||
|
ALIGN_UP(sizeof(OBJECT_ATTRIBUTES), sizeof(PVOID)));
|
||||||
|
|
||||||
|
RtlInitEmptyUnicodeString(ObjectName,
|
||||||
|
(PWCHAR)((ULONG_PTR)ObjectName +
|
||||||
|
ALIGN_UP(sizeof(UNICODE_STRING), sizeof(PVOID))),
|
||||||
|
StrSize);
|
||||||
|
|
||||||
|
|
||||||
|
/* If we got an inherited window station handle, duplicate and use it */
|
||||||
|
if (hWinSta)
|
||||||
|
{
|
||||||
|
ASSERT(bUseDefaultWinSta);
|
||||||
|
|
||||||
|
/* Duplicate the handle if it belongs to another process than the current one */
|
||||||
|
if (Process != PsGetCurrentProcess())
|
||||||
|
{
|
||||||
|
ASSERT(hProcess);
|
||||||
|
Status = ZwDuplicateObject(hProcess,
|
||||||
|
hWinSta,
|
||||||
|
ZwCurrentProcess(),
|
||||||
|
(PHANDLE)&hWinStaDup,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DUPLICATE_SAME_ACCESS);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("IntResolveDesktop: Failed to duplicate the window station handle, Status 0x%08lx\n", Status);
|
||||||
|
/* We will use a default window station */
|
||||||
|
hWinSta = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hWinSta = hWinStaDup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have an inherited window station, check whether
|
||||||
|
* it is interactive and remember that for later.
|
||||||
|
*/
|
||||||
|
if (hWinSta)
|
||||||
|
{
|
||||||
|
ASSERT(bUseDefaultWinSta);
|
||||||
|
|
||||||
|
/* Reference the inherited window station */
|
||||||
|
Status = ObReferenceObjectByHandle(hWinSta,
|
||||||
|
0,
|
||||||
|
ExWindowStationObjectType,
|
||||||
|
KernelMode,
|
||||||
|
(PVOID*)&WinStaObject,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("Failed to reference the inherited window station, Status 0x%08lx\n", Status);
|
||||||
|
/* We will use a default window station */
|
||||||
|
if (hWinStaDup)
|
||||||
|
{
|
||||||
|
ASSERT(hWinSta == hWinStaDup);
|
||||||
|
ObCloseHandle(hWinStaDup, UserMode);
|
||||||
|
hWinStaDup = NULL;
|
||||||
|
}
|
||||||
|
hWinSta = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Process LUID is: 0x%x-%x, inherited window station LUID is: 0x%x-%x\n",
|
||||||
|
ProcessLuid.HighPart, ProcessLuid.LowPart,
|
||||||
|
WinStaObject->luidUser.HighPart, WinStaObject->luidUser.LowPart);
|
||||||
|
|
||||||
|
/* Check whether this window station is interactive, and remember it for later */
|
||||||
|
bInteractive = !(WinStaObject->Flags & WSS_NOIO);
|
||||||
|
|
||||||
|
/* Dereference the window station */
|
||||||
|
ObDereferenceObject(WinStaObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a valid window station name */
|
||||||
|
Status = RtlStringCbPrintfW(ObjectName->Buffer,
|
||||||
|
ObjectName->MaximumLength,
|
||||||
|
L"%wZ\\%wZ",
|
||||||
|
&gustrWindowStationsDir,
|
||||||
|
&WinStaName);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("Impossible to build a valid window station name, Status 0x%08lx\n", Status);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
TRACE("Parsed initial window station: '%wZ'\n", ObjectName);
|
||||||
|
|
||||||
|
/* Try to open the window station */
|
||||||
|
InitializeObjectAttributes(ObjectAttributes,
|
||||||
|
ObjectName,
|
||||||
|
OBJ_CASE_INSENSITIVE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (bInherit)
|
||||||
|
ObjectAttributes->Attributes |= OBJ_INHERIT;
|
||||||
|
|
||||||
|
Status = ObOpenObjectByName(ObjectAttributes,
|
||||||
|
ExWindowStationObjectType,
|
||||||
|
UserMode,
|
||||||
|
NULL,
|
||||||
|
WINSTA_ACCESS_ALL,
|
||||||
|
NULL,
|
||||||
|
(PHANDLE)&hTempWinSta);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("Failed to open the window station '%wZ', Status 0x%08lx\n", ObjectName, Status);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME TODO: Perform a window station access check!!
|
||||||
|
// If we fail AND bUseDefaultWinSta == FALSE we just quit.
|
||||||
|
//
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether we are opening the (single) interactive
|
||||||
|
* window station, and if so, perform an access check.
|
||||||
|
*/
|
||||||
|
/* Check whether we are allowed to perform interactions */
|
||||||
|
if (RtlEqualUnicodeString(&WinStaName, &WinSta0Name, TRUE))
|
||||||
|
{
|
||||||
|
LUID SystemLuid = SYSTEM_LUID;
|
||||||
|
|
||||||
|
/* Interactive window station: check for user LUID */
|
||||||
|
WinStaObject = InputWindowStation;
|
||||||
|
|
||||||
|
Status = STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
|
// TODO: Check also that we compare wrt. window station WinSta0
|
||||||
|
// which is the only one that can be interactive on the system.
|
||||||
|
if (((!bUseDefaultWinSta || bInherit) && RtlEqualLuid(&ProcessLuid, &SystemLuid)) ||
|
||||||
|
RtlEqualLuid(&ProcessLuid, &WinStaObject->luidUser))
|
||||||
|
{
|
||||||
|
/* We are interactive on this window station */
|
||||||
|
bAccessAllowed = TRUE;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Non-interactive window station: we have access since we were able to open it */
|
||||||
|
bAccessAllowed = TRUE;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we failed, bail out if we were not trying to open the default window station */
|
||||||
|
if (!NT_SUCCESS(Status) && !bUseDefaultWinSta) // if (!bAccessAllowed)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
if (/* bAccessAllowed && */ bInteractive || !bAccessAllowed)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Close WinSta0 if the inherited window station is interactive so that
|
||||||
|
* we can use it, or we do not have access to the interactive WinSta0.
|
||||||
|
*/
|
||||||
|
ObCloseHandle(hTempWinSta, UserMode);
|
||||||
|
hTempWinSta = NULL;
|
||||||
|
}
|
||||||
|
if (bInteractive == bAccessAllowed)
|
||||||
|
{
|
||||||
|
/* Keep using the inherited window station */
|
||||||
|
NOTHING;
|
||||||
|
}
|
||||||
|
else // if (bInteractive != bAccessAllowed)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Close the inherited window station, we will either keep using
|
||||||
|
* the interactive WinSta0, or use Service-0xXXXX-YYYY$.
|
||||||
|
*/
|
||||||
|
if (hWinStaDup)
|
||||||
|
{
|
||||||
|
ASSERT(hWinSta == hWinStaDup);
|
||||||
|
ObCloseHandle(hWinStaDup, UserMode);
|
||||||
|
hWinStaDup = NULL;
|
||||||
|
}
|
||||||
|
hWinSta = hTempWinSta; // hTempWinSta is NULL in case bAccessAllowed == FALSE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bUseDefaultWinSta)
|
||||||
|
{
|
||||||
|
if (hWinSta == NULL && !bInteractive)
|
||||||
|
{
|
||||||
|
/* Build a valid window station name from the LUID */
|
||||||
|
Status = RtlStringCbPrintfW(ObjectName->Buffer,
|
||||||
|
ObjectName->MaximumLength,
|
||||||
|
L"%wZ\\Service-0x%x-%x$",
|
||||||
|
&gustrWindowStationsDir,
|
||||||
|
ProcessLuid.HighPart,
|
||||||
|
ProcessLuid.LowPart);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("Impossible to build a valid window station name, Status 0x%08lx\n", Status);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create or open the non-interactive window station.
|
||||||
|
* NOTE: The non-interactive window station handle is never inheritable.
|
||||||
|
*/
|
||||||
|
// FIXME: Set security!
|
||||||
|
InitializeObjectAttributes(ObjectAttributes,
|
||||||
|
ObjectName,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Status = IntCreateWindowStation(&hWinSta,
|
||||||
|
ObjectAttributes,
|
||||||
|
UserMode,
|
||||||
|
KernelMode,
|
||||||
|
MAXIMUM_ALLOWED,
|
||||||
|
0, 0, 0, 0, 0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ASSERT(hWinSta == NULL);
|
||||||
|
ERR("Failed to create or open the non-interactive window station '%wZ', Status 0x%08lx\n",
|
||||||
|
ObjectName, Status);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: We might not need to always create or open the "Default"
|
||||||
|
// desktop on the Service-0xXXXX-YYYY$ window station; we may need
|
||||||
|
// to use another one....
|
||||||
|
//
|
||||||
|
|
||||||
|
/* Create or open the Default desktop on the window station */
|
||||||
|
Status = RtlStringCbCopyW(ObjectName->Buffer,
|
||||||
|
ObjectName->MaximumLength,
|
||||||
|
L"Default");
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("Impossible to build a valid desktop name, Status 0x%08lx\n", Status);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
/* NOTE: The non-interactive desktop handle is never inheritable. */
|
||||||
|
// FIXME: Set security!
|
||||||
|
InitializeObjectAttributes(ObjectAttributes,
|
||||||
|
ObjectName,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
||||||
|
hWinSta,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Status = IntCreateDesktop(&hDesktop,
|
||||||
|
ObjectAttributes,
|
||||||
|
UserMode,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
MAXIMUM_ALLOWED);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ASSERT(hDesktop == NULL);
|
||||||
|
ERR("Failed to create or open the desktop '%wZ' on window station 0x%p, Status 0x%08lx\n",
|
||||||
|
ObjectName, hWinSta, Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (hWinSta == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we got an inherited desktop handle, duplicate and use it,
|
||||||
|
* otherwise open a new desktop.
|
||||||
|
*/
|
||||||
|
if (hDesktop != NULL)
|
||||||
|
{
|
||||||
|
/* Duplicate the handle if it belongs to another process than the current one */
|
||||||
|
if (Process != PsGetCurrentProcess())
|
||||||
|
{
|
||||||
|
ASSERT(hProcess);
|
||||||
|
Status = ZwDuplicateObject(hProcess,
|
||||||
|
hDesktop,
|
||||||
|
ZwCurrentProcess(),
|
||||||
|
(PHANDLE)&hDesktopDup,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DUPLICATE_SAME_ACCESS);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("IntResolveDesktop: Failed to duplicate the desktop handle, Status 0x%08lx\n", Status);
|
||||||
|
/* We will use a default desktop */
|
||||||
|
hDesktop = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hDesktop = hDesktopDup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hWinSta != NULL) && (hDesktop == NULL))
|
||||||
|
{
|
||||||
|
Status = RtlStringCbCopyNW(ObjectName->Buffer,
|
||||||
|
ObjectName->MaximumLength,
|
||||||
|
DesktopName.Buffer,
|
||||||
|
DesktopName.Length);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("Impossible to build a valid desktop name, Status 0x%08lx\n", Status);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
TRACE("Parsed initial desktop: '%wZ'\n", ObjectName);
|
||||||
|
|
||||||
/* Open the desktop object */
|
/* Open the desktop object */
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(ObjectAttributes,
|
||||||
&ObjectName,
|
ObjectName,
|
||||||
OBJ_CASE_INSENSITIVE,
|
OBJ_CASE_INSENSITIVE,
|
||||||
*hWinSta,
|
hWinSta,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (bInherit)
|
||||||
|
ObjectAttributes->Attributes |= OBJ_INHERIT;
|
||||||
|
|
||||||
Status = ObOpenObjectByName(&ObjectAttributes,
|
Status = ObOpenObjectByName(ObjectAttributes,
|
||||||
ExDesktopObjectType,
|
ExDesktopObjectType,
|
||||||
KernelMode,
|
UserMode,
|
||||||
NULL,
|
NULL,
|
||||||
DESKTOP_ALL_ACCESS,
|
DESKTOP_ALL_ACCESS,
|
||||||
NULL,
|
NULL,
|
||||||
(HANDLE*)hDesktop);
|
(PHANDLE)&hDesktop);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
*hDesktop = NULL;
|
ERR("Failed to open the desktop '%wZ' on window station 0x%p, Status 0x%08lx\n",
|
||||||
NtClose(*hWinSta);
|
ObjectName, hWinSta, Status);
|
||||||
*hWinSta = NULL;
|
goto Quit;
|
||||||
SetLastNtError(Status);
|
|
||||||
ERR("Failed to reference desktop %wZ PID: --!\n", &ObjectName);
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
Quit:
|
||||||
|
/* Release the object attributes */
|
||||||
|
if (ObjectAttributes)
|
||||||
|
{
|
||||||
|
MemSize = 0;
|
||||||
|
ZwFreeVirtualMemory(ZwCurrentProcess(),
|
||||||
|
(PVOID*)&ObjectAttributes,
|
||||||
|
&MemSize,
|
||||||
|
MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the temporary process handle */
|
||||||
|
if (hProcess) // if (Process != PsGetCurrentProcess())
|
||||||
|
ObCloseHandle(hProcess, KernelMode);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
*phWinSta = hWinSta;
|
||||||
|
*phDesktop = hDesktop;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("IntResolveDesktop(%wZ) failed, Status 0x%08lx\n", DesktopPath, Status);
|
||||||
|
|
||||||
|
if (hDesktopDup)
|
||||||
|
ObCloseHandle(hDesktopDup, UserMode);
|
||||||
|
if (hWinStaDup)
|
||||||
|
ObCloseHandle(hWinStaDup, UserMode);
|
||||||
|
|
||||||
|
if (hDesktop)
|
||||||
|
ObCloseHandle(hDesktop, UserMode);
|
||||||
|
if (hWinSta)
|
||||||
|
ObCloseHandle(hWinSta, UserMode);
|
||||||
|
|
||||||
|
SetLastNtError(Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2115,15 +2702,24 @@ NtUserPaintDesktop(HDC hDC)
|
||||||
/*
|
/*
|
||||||
* NtUserResolveDesktop
|
* NtUserResolveDesktop
|
||||||
*
|
*
|
||||||
* The NtUserResolveDesktop function retrieves handles to the desktop and
|
* The NtUserResolveDesktop function attempts to retrieve valid handles to
|
||||||
* the window station specified by the desktop path string.
|
* a desktop and a window station suitable for the specified process.
|
||||||
|
* The specified desktop path string is used only as a hint for the resolution.
|
||||||
|
*
|
||||||
|
* See the description of IntResolveDesktop for more details.
|
||||||
*
|
*
|
||||||
* Parameters
|
* Parameters
|
||||||
* ProcessHandle
|
* ProcessHandle
|
||||||
* Handle to a user process.
|
* Handle to a user process.
|
||||||
*
|
*
|
||||||
* DesktopPath
|
* DesktopPath
|
||||||
* The desktop path string.
|
* The desktop path string used as a hint for desktop resolution.
|
||||||
|
*
|
||||||
|
* bInherit
|
||||||
|
* Whether or not the returned handles are inheritable.
|
||||||
|
*
|
||||||
|
* phWinSta
|
||||||
|
* Pointer to a window station handle.
|
||||||
*
|
*
|
||||||
* Return Value
|
* Return Value
|
||||||
* Handle to the desktop (direct return value) and
|
* Handle to the desktop (direct return value) and
|
||||||
|
@ -2138,17 +2734,18 @@ NtUserPaintDesktop(HDC hDC)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HDESK
|
HDESK
|
||||||
APIENTRY
|
NTAPI
|
||||||
NtUserResolveDesktop(
|
NtUserResolveDesktop(
|
||||||
IN HANDLE ProcessHandle,
|
IN HANDLE ProcessHandle,
|
||||||
IN PUNICODE_STRING DesktopPath,
|
IN PUNICODE_STRING DesktopPath,
|
||||||
DWORD dwUnknown,
|
IN BOOL bInherit,
|
||||||
OUT HWINSTA* phWinSta)
|
OUT HWINSTA* phWinSta)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PEPROCESS Process = NULL;
|
PEPROCESS Process;
|
||||||
HWINSTA hWinSta = NULL;
|
HWINSTA hWinSta = NULL;
|
||||||
HDESK hDesktop = NULL;
|
HDESK hDesktop = NULL;
|
||||||
|
UNICODE_STRING CapturedDesktopPath;
|
||||||
|
|
||||||
/* Allow only the Console Server to perform this operation (via CSRSS) */
|
/* Allow only the Console Server to perform this operation (via CSRSS) */
|
||||||
if (PsGetCurrentProcess() != gpepCSRSS)
|
if (PsGetCurrentProcess() != gpepCSRSS)
|
||||||
|
@ -2161,44 +2758,63 @@ NtUserResolveDesktop(
|
||||||
UserMode,
|
UserMode,
|
||||||
(PVOID*)&Process,
|
(PVOID*)&Process,
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) return NULL;
|
if (!NT_SUCCESS(Status))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// UserEnterShared();
|
// UserEnterShared();
|
||||||
|
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
UNICODE_STRING CapturedDesktopPath;
|
/* Probe the handle pointer */
|
||||||
|
// ProbeForWriteHandle
|
||||||
/* Capture the user desktop path string */
|
ProbeForWrite(phWinSta, sizeof(HWINSTA), sizeof(HWINSTA));
|
||||||
Status = IntSafeCopyUnicodeStringTerminateNULL(&CapturedDesktopPath,
|
|
||||||
DesktopPath);
|
|
||||||
if (!NT_SUCCESS(Status)) _SEH2_YIELD(goto Quit);
|
|
||||||
|
|
||||||
/* Call the internal function */
|
|
||||||
Status = IntParseDesktopPath(Process,
|
|
||||||
&CapturedDesktopPath,
|
|
||||||
&hWinSta,
|
|
||||||
&hDesktop);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ERR("IntParseDesktopPath failed, Status = 0x%08lx\n", Status);
|
|
||||||
hWinSta = NULL;
|
|
||||||
hDesktop = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the window station handle */
|
|
||||||
*phWinSta = hWinSta;
|
|
||||||
|
|
||||||
/* Free the captured string */
|
|
||||||
if (CapturedDesktopPath.Buffer)
|
|
||||||
ExFreePoolWithTag(CapturedDesktopPath.Buffer, TAG_STRING);
|
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
Status = _SEH2_GetExceptionCode();
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
_SEH2_YIELD(goto Quit);
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
|
/* Capture the user desktop path string */
|
||||||
|
Status = ProbeAndCaptureUnicodeString(&CapturedDesktopPath,
|
||||||
|
UserMode,
|
||||||
|
DesktopPath);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
/* Call the internal function */
|
||||||
|
Status = IntResolveDesktop(Process,
|
||||||
|
&CapturedDesktopPath,
|
||||||
|
bInherit,
|
||||||
|
&hWinSta,
|
||||||
|
&hDesktop);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("IntResolveDesktop failed, Status 0x%08lx\n", Status);
|
||||||
|
hWinSta = NULL;
|
||||||
|
hDesktop = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
/* Return the window station handle */
|
||||||
|
*phWinSta = hWinSta;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
|
||||||
|
/* We failed, close the opened desktop and window station */
|
||||||
|
if (hDesktop) ObCloseHandle(hDesktop, UserMode);
|
||||||
|
hDesktop = NULL;
|
||||||
|
if (hWinSta) ObCloseHandle(hWinSta, UserMode);
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
/* Free the captured string */
|
||||||
|
ReleaseCapturedUnicodeString(&CapturedDesktopPath, UserMode);
|
||||||
|
|
||||||
Quit:
|
Quit:
|
||||||
// UserLeave();
|
// UserLeave();
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,15 @@ IntHideDesktop(PDESKTOP Desktop);
|
||||||
BOOL IntSetThreadDesktop(IN HDESK hDesktop,
|
BOOL IntSetThreadDesktop(IN HDESK hDesktop,
|
||||||
IN BOOL FreeOnFailure);
|
IN BOOL FreeOnFailure);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
FASTCALL
|
||||||
|
IntResolveDesktop(
|
||||||
|
IN PEPROCESS Process,
|
||||||
|
IN PUNICODE_STRING DesktopPath,
|
||||||
|
IN BOOL bInherit,
|
||||||
|
OUT HWINSTA* phWinSta,
|
||||||
|
OUT HDESK* phDesktop);
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
IntValidateDesktopHandle(
|
IntValidateDesktopHandle(
|
||||||
HDESK Desktop,
|
HDESK Desktop,
|
||||||
|
@ -179,12 +188,6 @@ IntCreateDesktop(
|
||||||
IN DWORD dwFlags,
|
IN DWORD dwFlags,
|
||||||
IN ACCESS_MASK dwDesiredAccess);
|
IN ACCESS_MASK dwDesiredAccess);
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
|
||||||
IntParseDesktopPath(PEPROCESS Process,
|
|
||||||
PUNICODE_STRING DesktopPath,
|
|
||||||
HWINSTA *hWinSta,
|
|
||||||
HDESK *hDesktop);
|
|
||||||
|
|
||||||
VOID APIENTRY UserRedrawDesktop(VOID);
|
VOID APIENTRY UserRedrawDesktop(VOID);
|
||||||
BOOL IntRegisterShellHookWindow(HWND hWnd);
|
BOOL IntRegisterShellHookWindow(HWND hWnd);
|
||||||
BOOL IntDeRegisterShellHookWindow(HWND hWnd);
|
BOOL IntDeRegisterShellHookWindow(HWND hWnd);
|
||||||
|
|
|
@ -532,12 +532,12 @@ InitThreadCallback(PETHREAD Thread)
|
||||||
|
|
||||||
ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
|
ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
|
||||||
|
|
||||||
|
// FIXME: Flag SYSTEM threads with... TIF_SYSTEMTHREAD !!
|
||||||
|
|
||||||
/* CSRSS threads have some special features */
|
/* CSRSS threads have some special features */
|
||||||
if (Process == gpepCSRSS)
|
if (Process == gpepCSRSS)
|
||||||
ptiCurrent->TIF_flags = TIF_CSRSSTHREAD | TIF_DONTATTACHQUEUE;
|
ptiCurrent->TIF_flags = TIF_CSRSSTHREAD | TIF_DONTATTACHQUEUE;
|
||||||
|
|
||||||
// FIXME: Flag SYSTEM threads with... TIF_SYSTEMTHREAD !!
|
|
||||||
|
|
||||||
ptiCurrent->pcti = &ptiCurrent->cti;
|
ptiCurrent->pcti = &ptiCurrent->cti;
|
||||||
|
|
||||||
/* Initialize the CLIENTINFO */
|
/* Initialize the CLIENTINFO */
|
||||||
|
@ -570,9 +570,16 @@ InitThreadCallback(PETHREAD Thread)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign a default window station and desktop to the process */
|
/*
|
||||||
/* Do not try to open a desktop or window station before winlogon initializes */
|
* Assign a default window station and desktop to the process.
|
||||||
if (ptiCurrent->ppi->hdeskStartup == NULL && gpidLogon != 0)
|
* Do not try to open a desktop or window station before the very first
|
||||||
|
* (interactive) window station has been created by Winlogon.
|
||||||
|
*/
|
||||||
|
// if (ptiCurrent->ppi->hdeskStartup == NULL && InputWindowStation != NULL)
|
||||||
|
/* Last things to do only if we are not a SYSTEM or CSRSS thread */
|
||||||
|
if (!(ptiCurrent->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) &&
|
||||||
|
/**/ptiCurrent->ppi->hdeskStartup == NULL &&/**/
|
||||||
|
InputWindowStation != NULL)
|
||||||
{
|
{
|
||||||
HWINSTA hWinSta = NULL;
|
HWINSTA hWinSta = NULL;
|
||||||
HDESK hDesk = NULL;
|
HDESK hDesk = NULL;
|
||||||
|
@ -580,8 +587,8 @@ InitThreadCallback(PETHREAD Thread)
|
||||||
PDESKTOP pdesk;
|
PDESKTOP pdesk;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* inherit the thread desktop and process window station (if not yet inherited) from the process startup
|
* Inherit the thread desktop and process window station (if not yet inherited)
|
||||||
* info structure. See documentation of CreateProcess()
|
* from the process startup info structure. See documentation of CreateProcess().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
|
@ -594,17 +601,18 @@ InitThreadCallback(PETHREAD Thread)
|
||||||
RtlInitUnicodeString(&DesktopPath, NULL);
|
RtlInitUnicodeString(&DesktopPath, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = IntParseDesktopPath(Process,
|
Status = IntResolveDesktop(Process,
|
||||||
&DesktopPath,
|
&DesktopPath,
|
||||||
&hWinSta,
|
FALSE,
|
||||||
&hDesk);
|
&hWinSta,
|
||||||
|
&hDesk);
|
||||||
|
|
||||||
if (DesktopPath.Buffer)
|
if (DesktopPath.Buffer)
|
||||||
ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING);
|
ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n");
|
ERR_CH(UserThread, "Failed to assign default desktop and winsta to process\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,7 +623,7 @@ InitThreadCallback(PETHREAD Thread)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validate the new desktop. */
|
/* Validate the new desktop */
|
||||||
Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
|
Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -624,6 +632,8 @@ InitThreadCallback(PETHREAD Thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the parsed desktop as the initial desktop */
|
/* Store the parsed desktop as the initial desktop */
|
||||||
|
ASSERT(ptiCurrent->ppi->hdeskStartup == NULL);
|
||||||
|
ASSERT(Process->UniqueProcessId != gpidLogon);
|
||||||
ptiCurrent->ppi->hdeskStartup = hDesk;
|
ptiCurrent->ppi->hdeskStartup = hDesk;
|
||||||
ptiCurrent->ppi->rpdeskStartup = pdesk;
|
ptiCurrent->ppi->rpdeskStartup = pdesk;
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,7 +324,7 @@ GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo,
|
||||||
|
|
||||||
hDesk = NtUserResolveDesktop(ConsoleLeaderProcessHandle,
|
hDesk = NtUserResolveDesktop(ConsoleLeaderProcessHandle,
|
||||||
&DesktopPath,
|
&DesktopPath,
|
||||||
0,
|
FALSE,
|
||||||
&hWinSta);
|
&hWinSta);
|
||||||
DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n",
|
DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n",
|
||||||
&DesktopPath, hDesk, hWinSta);
|
&DesktopPath, hDesk, hWinSta);
|
||||||
|
|
Loading…
Reference in a new issue