https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1dfba2a699d76c7974d6e…
commit 1dfba2a699d76c7974d6ec874c64f6c1f86914ec
Author: Thamatip Chitpong <thamatip.chitpong(a)reactos.org>
AuthorDate: Wed Jan 8 08:28:24 2025 +0700
Commit: GitHub <noreply(a)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);