From 78ce856564dfbe143d5b37f76be96e2e92cdd037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Tue, 15 Jul 2025 15:12:44 +0200 Subject: [PATCH] [WINLOGON] Duplicate the logged-in user/domain names and give them to the notifications (#8322) Test results: - Test 1a: `Asynchronous: FALSE, Impersonation: FALSE` BEFORE the fix: OK, the thread isn't impersonated: ``` Thread Token : 0x00000000 - User: '(null)\(null)' ``` BUT these two WLX notify info fields aren't set when the user is logged in: ``` Info.UserName : '(null)' Info.Domain : '(null)' ``` Results: ``` WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped. WLEventLogon: 30 tests executed (0 marked as todo, 3 failures), 2 skipped. WLEventStartShell: 30 tests executed (0 marked as todo, 3 failures), 2 skipped. (NOTE: WLEventPostShell isn't yet implemented in ReactOS) WLEventLock: 30 tests executed (0 marked as todo, 4 failures), 2 skipped. WLEventUnlock: 30 tests executed (0 marked as todo, 3 failures), 2 skipped. WLEventStartScreenSaver: 30 tests executed (0 marked as todo, 9 failures), 2 skipped. WLEventStopScreenSaver: 30 tests executed (0 marked as todo, 7 failures), 2 skipped. WLEventLogoff: 30 tests executed (0 marked as todo, 4 failures), 2 skipped. WLEventShutdown: 31 tests executed (0 marked as todo, 3 failures), 0 skipped. ``` - Test 1b: `Asynchronous: FALSE, Impersonation: FALSE` AFTER the fix: OK, the thread isn't impersonated: ``` Thread Token : 0x00000000 - User: '(null)\(null)' ``` OK, these two WLX notify info fields are now set when the user is logged in: ``` Info.UserName : 'Administrator' Info.Domain : 'MYCOMPUTERNAME' ``` Results: ``` WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped. WLEventLogon: 32 tests executed (0 marked as todo, 1 failure), 0 skipped. WLEventStartShell: 32 tests executed (0 marked as todo, 1 failure), 0 skipped. (NOTE: WLEventPostShell isn't yet implemented in ReactOS) WLEventLock: 32 tests executed (0 marked as todo, 2 failures), 0 skipped. WLEventUnlock: 32 tests executed (0 marked as todo, 1 failure), 0 skipped. WLEventStartScreenSaver: 32 tests executed (0 marked as todo, 7 failures), 0 skipped. WLEventStopScreenSaver: 32 tests executed (0 marked as todo, 5 failures), 0 skipped. WLEventLogoff: 32 tests executed (0 marked as todo, 2 failures), 0 skipped. WLEventShutdown: 31 tests executed (0 marked as todo, 3 failures), 0 skipped. ``` Less failed tests and none skipped anymore. - Test 2a: `Asynchronous: FALSE, Impersonation: TRUE` BEFORE the fix: OK, the thread impersonates the user when (s)he is logged in: ``` Thread Token : 0x00000360 - User: 'MYCOMPUTERNAME\Administrator' ``` BUT these two WLX notify info fields aren't set when the user is logged in: ``` Info.UserName : '(null)' Info.Domain : '(null)' ``` Results: ``` WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped. WLEventLogon: 31 tests executed (0 marked as todo, 5 failures), 2 skipped. WLEventStartShell: 31 tests executed (0 marked as todo, 5 failures), 2 skipped. (NOTE: WLEventPostShell isn't yet implemented in ReactOS) WLEventLock: 31 tests executed (0 marked as todo, 6 failures), 2 skipped. WLEventUnlock: 31 tests executed (0 marked as todo, 5 failures), 2 skipped. WLEventStartScreenSaver: 32 tests executed (0 marked as todo, 6 failures), 2 skipped. WLEventStopScreenSaver: 32 tests executed (0 marked as todo, 4 failures), 2 skipped. WLEventLogoff: 32 tests executed (0 marked as todo, 4 failures), 2 skipped. WLEventShutdown: 31 tests executed (0 marked as todo, 3 failures), 0 skipped. ``` - Test 2b: `Asynchronous: FALSE, Impersonation: TRUE` AFTER the fix: OK, the thread impersonates the user when (s)he is logged in: ``` Thread Token : 0x00000360 - User: 'MYCOMPUTERNAME\Administrator' ``` OK, these two WLX notify info fields are now set when the user is logged in: ``` Info.UserName : 'Administrator' Info.Domain : 'MYCOMPUTERNAME' ``` Results: ``` WLEventStartup: 30 tests executed (0 marked as todo, 1 failure), 0 skipped. WLEventLogon: 33 tests executed (0 marked as todo, 3 failures), 0 skipped. WLEventStartShell: 33 tests executed (0 marked as todo, 3 failures), 0 skipped. (NOTE: WLEventPostShell isn't yet implemented in ReactOS) WLEventLock: 33 tests executed (0 marked as todo, 4 failures), 0 skipped. WLEventUnlock: 33 tests executed (0 marked as todo, 3 failures), 0 skipped. WLEventStartScreenSaver: 34 tests executed (0 marked as todo, 4 failures), 0 skipped. WLEventStopScreenSaver: 34 tests executed (0 marked as todo, 2 failures), 0 skipped. WLEventLogoff: 34 tests executed (0 marked as todo, 2 failures), 0 skipped. WLEventShutdown: 31 tests executed (0 marked as todo, 3 failures), 0 skipped. ``` As well, less failed tests and none skipped anymore. --- base/system/winlogon/notify.c | 14 ++++---------- base/system/winlogon/sas.c | 12 ++++++++++++ base/system/winlogon/winlogon.c | 21 +++++++++++++++++++++ base/system/winlogon/winlogon.h | 8 +++++++- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/base/system/winlogon/notify.c b/base/system/winlogon/notify.c index 56ef94b5001..5dbdad2eb3f 100644 --- a/base/system/winlogon/notify.c +++ b/base/system/winlogon/notify.c @@ -190,16 +190,13 @@ AddSfcNotification(VOID) if (!NotificationDll) return; // If needed: dwError = ERROR_OUTOFMEMORY; - NotificationDll->pszDllName = RtlAllocateHeap(RtlGetProcessHeap(), 0, - (wcslen(szSfcPath) + 1) * sizeof(WCHAR)); + NotificationDll->pszDllName = WlStrDup(szSfcPath); if (NotificationDll->pszDllName == NULL) { dwError = ERROR_OUTOFMEMORY; goto done; } - wcscpy(NotificationDll->pszDllName, szSfcPath); - NotificationDll->bEnabled = TRUE; NotificationDll->dwMaxWait = 30; /* FIXME: ??? */ NotificationDll->bSfcNotification = TRUE; @@ -290,16 +287,13 @@ AddNotificationDll( goto done; } - NotificationDll->pszKeyName = RtlAllocateHeap(RtlGetProcessHeap(), 0, - (wcslen(pszKeyName) + 1) * sizeof(WCHAR)); + NotificationDll->pszKeyName = WlStrDup(pszKeyName); if (NotificationDll->pszKeyName == NULL) { lError = ERROR_OUTOFMEMORY; goto done; } - wcscpy(NotificationDll->pszKeyName, pszKeyName); - dwSize = 0; lError = RegQueryValueExW(hDllKey, L"DllName", @@ -560,8 +554,8 @@ CallNotificationDlls( break; } - Info.UserName = NULL; //UserName; - Info.Domain = NULL; //Domain; + Info.UserName = pSession->UserName; + Info.Domain = pSession->Domain; Info.WindowStation = pSession->InteractiveWindowStationName; Info.hToken = pSession->UserToken; diff --git a/base/system/winlogon/sas.c b/base/system/winlogon/sas.c index 975acce1592..8a23b01d562 100644 --- a/base/system/winlogon/sas.c +++ b/base/system/winlogon/sas.c @@ -621,6 +621,10 @@ HandleLogon( Session->hProfileInfo = ProfileInfo.hProfile; } + /* Cache the username and domain */ + Session->UserName = WlStrDup(Session->MprNotifyInfo.pszUserName); + Session->Domain = WlStrDup(Session->MprNotifyInfo.pszDomain); + /* Create environment block for the user */ if (!CreateUserEnvironment(Session)) { @@ -687,6 +691,10 @@ cleanup: if (!ret) { + RtlFreeHeap(RtlGetProcessHeap(), 0, Session->UserName); + RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Domain); + Session->UserName = Session->Domain = NULL; + if (Session->hProfileInfo) UnloadUserProfile(Session->UserToken, Session->hProfileInfo); Session->hProfileInfo = NULL; @@ -1050,6 +1058,10 @@ HandleLogoff( DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_SAVEYOURSETTINGS); + RtlFreeHeap(RtlGetProcessHeap(), 0, Session->UserName); + RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Domain); + Session->UserName = Session->Domain = NULL; + if (Session->hProfileInfo) UnloadUserProfile(Session->UserToken, Session->hProfileInfo); Session->hProfileInfo = NULL; diff --git a/base/system/winlogon/winlogon.c b/base/system/winlogon/winlogon.c index 2f4f4177821..022d529149a 100644 --- a/base/system/winlogon/winlogon.c +++ b/base/system/winlogon/winlogon.c @@ -21,6 +21,27 @@ PWLSESSION WLSession = NULL; /* FUNCTIONS *****************************************************************/ +/** + * @brief + * Duplicates the given string, allocating a buffer on the heap. + **/ +PWSTR +WlStrDup( + _In_opt_ PCWSTR String) +{ + PWSTR ptr; + + if (!String) + return NULL; + + ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, + (wcslen(String) + 1) * sizeof(WCHAR)); + if (ptr) + wcscpy(ptr, String); + return ptr; +} + + static BOOL StartServicesManager(VOID) diff --git a/base/system/winlogon/winlogon.h b/base/system/winlogon/winlogon.h index 23272cf8995..e90d0a0031a 100644 --- a/base/system/winlogon/winlogon.h +++ b/base/system/winlogon/winlogon.h @@ -227,7 +227,9 @@ typedef struct _WLSESSION BOOL UtilManHotkey; HWND SASWindow; HWINSTA InteractiveWindowStation; - LPWSTR InteractiveWindowStationName; + PWSTR InteractiveWindowStationName; + PWSTR UserName; + PWSTR Domain; HDESK ApplicationDesktop; HDESK WinlogonDesktop; HDESK ScreenSaverDesktop; @@ -403,6 +405,10 @@ StartSystemShutdown( IN ULONG dwReason); /* winlogon.c */ +PWSTR +WlStrDup( + _In_opt_ PCWSTR String); + BOOL PlaySoundRoutine(IN LPCWSTR FileName, IN UINT Logon,