https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1dfba2a699d76c7974d6ec874c64f6c1f86914ec

commit 1dfba2a699d76c7974d6ec874c64f6c1f86914ec
Author:     Thamatip Chitpong <thamatip.chitp...@reactos.org>
AuthorDate: Wed Jan 8 08:28:24 2025 +0700
Commit:     GitHub <nore...@github.com>
CommitDate: Wed Jan 8 08:28:24 2025 +0700

    [WINLOGON] Add WLSESSION logon timestamp (#7590)
    
    Remove startup sound hack.
    CORE-13951
---
 base/system/winlogon/sas.c      | 62 ++++++++++++++++++++++++-----------------
 base/system/winlogon/winlogon.h | 19 +++++++++++++
 2 files changed, 55 insertions(+), 26 deletions(-)

diff --git a/base/system/winlogon/sas.c b/base/system/winlogon/sas.c
index 8b169f73df6..17c7778e13a 100644
--- a/base/system/winlogon/sas.c
+++ b/base/system/winlogon/sas.c
@@ -46,6 +46,12 @@ static BOOL ExitReactOSInProgress = FALSE;
 
 LUID LuidNone = {0, 0};
 
+typedef struct tagLOGON_SOUND_DATA
+{
+    HANDLE UserToken;
+    BOOL IsStartup;
+} LOGON_SOUND_DATA, *PLOGON_SOUND_DATA;
+
 /* FUNCTIONS ****************************************************************/
 
 static BOOL
@@ -286,26 +292,12 @@ PlaySoundRoutine(
 }
 
 static
-BOOL
-IsFirstLogon(VOID)
-{
-    /* FIXME: All of this is a HACK, designed specifically for 
PlayLogonSoundThread.
-     * Don't call IsFirstLogon multiple times inside the same function. And 
please
-     * note that this function is not thread-safe. */
-    static BOOL bFirstLogon = TRUE;
-    if (bFirstLogon)
-    {
-        bFirstLogon = FALSE;
-        return TRUE;
-    }
-    return FALSE;
-}
-
 DWORD
 WINAPI
 PlayLogonSoundThread(
-    IN LPVOID lpParameter)
+    _In_ LPVOID lpParameter)
 {
+    PLOGON_SOUND_DATA SoundData = (PLOGON_SOUND_DATA)lpParameter;
     SERVICE_STATUS_PROCESS Info;
     DWORD dwSize;
     ULONG Index = 0;
@@ -316,7 +308,7 @@ PlayLogonSoundThread(
     if (!hSCManager)
     {
         ERR("OpenSCManager failed (%x)\n", GetLastError());
-        return 0;
+        goto Cleanup;
     }
 
     /* Open the wdmaud service */
@@ -326,7 +318,7 @@ PlayLogonSoundThread(
         /* The service is not installed */
         TRACE("Failed to open wdmaud service (%x)\n", GetLastError());
         CloseServiceHandle(hSCManager);
-        return 0;
+        goto Cleanup;
     }
 
     /* Wait for wdmaud to start */
@@ -352,35 +344,50 @@ PlayLogonSoundThread(
     if (Info.dwCurrentState != SERVICE_RUNNING)
     {
         WARN("wdmaud has not started!\n");
-        return 0;
+        goto Cleanup;
     }
 
     /* Sound subsystem is running. Play logon sound. */
-    TRACE("Playing logon sound\n");
-    if (!ImpersonateLoggedOnUser((HANDLE)lpParameter))
+    TRACE("Playing %s sound\n", SoundData->IsStartup ? "startup" : "logon");
+    if (!ImpersonateLoggedOnUser(SoundData->UserToken))
     {
         ERR("ImpersonateLoggedOnUser failed (%x)\n", GetLastError());
     }
     else
     {
-        PlaySoundRoutine(IsFirstLogon() ? L"SystemStart" : L"WindowsLogon",
+        PlaySoundRoutine(SoundData->IsStartup ? L"SystemStart" : 
L"WindowsLogon",
                          TRUE,
                          SND_ALIAS | SND_NODEFAULT);
         RevertToSelf();
     }
+
+Cleanup:
+    HeapFree(GetProcessHeap(), 0, SoundData);
     return 0;
 }
 
 static
 VOID
 PlayLogonSound(
-    IN OUT PWLSESSION Session)
+    _In_ PWLSESSION Session)
 {
+    PLOGON_SOUND_DATA SoundData;
     HANDLE hThread;
 
-    hThread = CreateThread(NULL, 0, PlayLogonSoundThread, 
(PVOID)Session->UserToken, 0, NULL);
-    if (hThread)
-        CloseHandle(hThread);
+    SoundData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGON_SOUND_DATA));
+    if (!SoundData)
+        return;
+
+    SoundData->UserToken = Session->UserToken;
+    SoundData->IsStartup = IsFirstLogon(Session);
+
+    hThread = CreateThread(NULL, 0, PlayLogonSoundThread, SoundData, 0, NULL);
+    if (!hThread)
+    {
+        HeapFree(GetProcessHeap(), 0, SoundData);
+        return;
+    }
+    CloseHandle(hThread);
 }
 
 static
@@ -571,6 +578,9 @@ HandleLogon(
     /* Logon has succeeded. Play sound. */
     PlayLogonSound(Session);
 
+    /* NOTE: The logon timestamp has to be set after calling PlayLogonSound
+     * to correctly detect the startup event (first logon) */
+    SetLogonTimestamp(Session);
     ret = TRUE;
 
 cleanup:
diff --git a/base/system/winlogon/winlogon.h b/base/system/winlogon/winlogon.h
index 3dcf6fda0c3..4df8e00e632 100644
--- a/base/system/winlogon/winlogon.h
+++ b/base/system/winlogon/winlogon.h
@@ -41,6 +41,7 @@
 #include <winwlx.h>
 #include <ndk/rtlfuncs.h>
 #include <ndk/exfuncs.h>
+#include <ndk/kefuncs.h>
 #include <strsafe.h>
 
 /* PSEH for SEH Support */
@@ -233,6 +234,7 @@ typedef struct _WLSESSION
     HANDLE hProfileInfo;
     LOGON_STATE LogonState;
     DWORD DialogTimeout; /* Timeout for dialog boxes, in seconds */
+    LARGE_INTEGER LastLogon;
 
     /* Screen-saver informations */
 #ifndef USE_GETLASTINPUTINFO
@@ -285,6 +287,23 @@ extern PWLSESSION WLSession;
    ((Status) == WLX_SAS_ACTION_SHUTDOWN_HIBERNATE) \
   )
 
+FORCEINLINE
+VOID
+SetLogonTimestamp(
+    _Inout_ PWLSESSION Session)
+{
+    NtQuerySystemTime(&Session->LastLogon);
+}
+
+FORCEINLINE
+BOOL
+IsFirstLogon(
+    _In_ PWLSESSION Session)
+{
+    /* The WLSESSION::LastLogon is initialized to 0 so this is OK */
+    return (Session->LastLogon.QuadPart == 0);
+}
+
 /* environment.c */
 BOOL
 CreateUserEnvironment(IN PWLSESSION Session);

Reply via email to