[WIN32SS:NTUSER] Improve initialization of window station and desktop objects

As soon as `ObCreateObject()` is successfully invoked, zero-out the winsta
and desktop object buffers and assign them the current process session ID
(into their first `dwSessionId` member). Only then, continue with regular
initialization.

It's done in this systematic way in order to ensure that, in case the
regular initialization of these objects fails and `ObDereferenceObject()`
is invoked, the `nt!ExpWin32SessionCallout()` routine (in `ntoskrnl/ex/win32k.c`)
that is executed as part of the Win32 "delete" object callback registered
by win32k.sys with the Object Manager, correctly finds a valid initialized
`SessionId` value in the "common header" of either the window station
or the desktop object being deleted.

As a side-result, other parts of win32k can directly refer to
`pdesk->dwSessionId` instead of `pdesk->rpwinstaParent->dwSessionId`
for a given desktop.
This commit is contained in:
Hermès Bélusca-Maïto
2026-06-11 18:03:17 +02:00
parent 1968202840
commit 2eb28656da
3 changed files with 14 additions and 10 deletions

View File

@@ -143,7 +143,13 @@ IntDesktopObjectParse(IN PVOID ParseObject,
0,
0,
(PVOID*)&Desktop);
if (!NT_SUCCESS(Status)) return Status;
if (!NT_SUCCESS(Status))
return Status;
RtlZeroMemory(Desktop, sizeof(DESKTOP));
/* Assign the session ID to the desktop */
Desktop->dwSessionId = PsGetCurrentProcessSessionId(); // gSessionId
ASSERT(Desktop->dwSessionId == WinStaObject->dwSessionId);
/* Assign security to the desktop we have created */
Status = IntAssignDesktopSecurityOnParse(WinStaObject, Desktop, AccessState);
@@ -2278,8 +2284,6 @@ UserInitializeDesktop(PDESKTOP pdesk, PUNICODE_STRING DesktopName, PWINSTATION_O
TRACE("UserInitializeDesktop desktop 0x%p with name %wZ\n", pdesk, DesktopName);
RtlZeroMemory(pdesk, sizeof(DESKTOP));
/* Set desktop size, based on whether the WinSta is interactive or not */
if (pwinsta == InputWindowStation)
{
@@ -2488,8 +2492,7 @@ IntCreateDesktop(
}
pWnd->fnid = FNID_DESKTOP;
/* Assign the session ID and the desktop window to the desktop */
pdesk->dwSessionId = PsGetCurrentProcessSessionId();
/* Assign the desktop window to the desktop */
pdesk->DesktopWindow = UserHMGetHandle(pWnd);
pdesk->pDeskInfo->spwnd = pWnd;
@@ -2982,7 +2985,7 @@ NtUserSwitchDesktop(HDESK hdesk)
goto Exit; // Return FALSE
}
if (PsGetCurrentProcessSessionId() != pdesk->rpwinstaParent->dwSessionId)
if (PsGetCurrentProcessSessionId() != pdesk->dwSessionId)
{
ObDereferenceObject(pdesk);
ERR("NtUserSwitchDesktop called for a desktop of a different session\n");

View File

@@ -321,7 +321,7 @@ IntDestroyMenuObject(PMENU Menu, BOOL bRecurse)
{
PWND Window;
if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId)
if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->dwSessionId)
{
BOOL ret;
if (Menu->hWnd)

View File

@@ -504,12 +504,13 @@ IntCreateWindowStation(
SetLastNtError(Status);
return Status;
}
/* Initialize the window station */
RtlZeroMemory(WindowStation, sizeof(WINSTATION_OBJECT));
/* Assign the session ID to the window station */
WindowStation->dwSessionId = PsGetCurrentProcessSessionId(); // gSessionId
/* Initialize the window station */
InitializeListHead(&WindowStation->DesktopListHead);
WindowStation->dwSessionId = NtCurrentPeb()->SessionId;
Status = RtlCreateAtomTable(37, &WindowStation->AtomTable);
if (!NT_SUCCESS(Status))
{