From 2eb28656dab579eaebf00d27cd58582142f4f9f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 11 Jun 2026 18:03:17 +0200 Subject: [PATCH] [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. --- win32ss/user/ntuser/desktop.c | 15 +++++++++------ win32ss/user/ntuser/menu.c | 2 +- win32ss/user/ntuser/winsta.c | 7 ++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/win32ss/user/ntuser/desktop.c b/win32ss/user/ntuser/desktop.c index 7419b4e446f..23d67960dc8 100644 --- a/win32ss/user/ntuser/desktop.c +++ b/win32ss/user/ntuser/desktop.c @@ -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"); diff --git a/win32ss/user/ntuser/menu.c b/win32ss/user/ntuser/menu.c index f35535c8024..747ed0ca2d3 100644 --- a/win32ss/user/ntuser/menu.c +++ b/win32ss/user/ntuser/menu.c @@ -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) diff --git a/win32ss/user/ntuser/winsta.c b/win32ss/user/ntuser/winsta.c index 1c32f99c683..116618aafcc 100644 --- a/win32ss/user/ntuser/winsta.c +++ b/win32ss/user/ntuser/winsta.c @@ -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)) {