LUID LuidNone = {0, 0};
+typedef struct tagLOGON_SOUND_DATA
+{
+ HANDLE UserToken;
+ BOOL IsStartup;
+} LOGON_SOUND_DATA, *PLOGON_SOUND_DATA;
+
/* FUNCTIONS ****************************************************************/
static BOOL
}
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;
if (!hSCManager)
{
ERR("OpenSCManager failed (%x)\n", GetLastError());
- return 0;
+ goto Cleanup;
}
/* Open the wdmaud service */
/* 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 */
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
/* 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:
#include <winwlx.h>
#include <ndk/rtlfuncs.h>
#include <ndk/exfuncs.h>
+#include <ndk/kefuncs.h>
#include <strsafe.h>
/* PSEH for SEH Support */
HANDLE hProfileInfo;
LOGON_STATE LogonState;
DWORD DialogTimeout; /* Timeout for dialog boxes, in seconds */
+ LARGE_INTEGER LastLogon;
/* Screen-saver informations */
#ifndef USE_GETLASTINPUTINFO
((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);