#define HK_CTRL_ALT_DEL 0
#define HK_CTRL_SHIFT_ESC 1
-extern BOOL WINAPI SetLogonNotifyWindow(HWND Wnd, HWINSTA WinSta);
+static BOOL inScrn = FALSE;
/* FUNCTIONS ****************************************************************/
return ret;
}
+static BOOL
+StartUserShell(
+ IN OUT PWLSESSION Session)
+{
+ LPVOID lpEnvironment = NULL;
+ BOOLEAN Old;
+ BOOL ret;
+
+ /* Create environment block for the user */
+ if (!CreateEnvironmentBlock(&lpEnvironment, Session->UserToken, TRUE))
+ {
+ WARN("WL: CreateEnvironmentBlock() failed\n");
+ return FALSE;
+ }
+
+ /* Get privilege */
+ /* FIXME: who should do it? winlogon or gina? */
+ /* FIXME: reverting to lower privileges after creating user shell? */
+ RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old);
+
+ ret = Session->Gina.Functions.WlxActivateUserShell(
+ Session->Gina.Context,
+ L"Default",
+ NULL, /* FIXME */
+ lpEnvironment);
+
+ DestroyEnvironmentBlock(lpEnvironment);
+ return ret;
+}
+
+
BOOL
SetDefaultLanguage(
IN BOOL UserProfile)
return ret;
}
+BOOL
+PlaySoundRoutine(
+ IN LPCWSTR FileName,
+ IN UINT bLogon,
+ IN UINT Flags)
+{
+ typedef BOOL (WINAPI *PLAYSOUNDW)(LPCWSTR,HMODULE,DWORD);
+ typedef UINT (WINAPI *WAVEOUTGETNUMDEVS)(VOID);
+ PLAYSOUNDW Play;
+ WAVEOUTGETNUMDEVS waveOutGetNumDevs;
+ UINT NumDevs;
+ HMODULE hLibrary;
+ BOOL Ret = FALSE;
+
+ hLibrary = LoadLibraryW(L"winmm.dll");
+ if (hLibrary)
+ {
+ waveOutGetNumDevs = (WAVEOUTGETNUMDEVS)GetProcAddress(hLibrary, "waveOutGetNumDevs");
+ if (waveOutGetNumDevs)
+ {
+ NumDevs = waveOutGetNumDevs();
+ if (!NumDevs)
+ {
+ if (!bLogon)
+ {
+ Beep(500, 500);
+ }
+ FreeLibrary(hLibrary);
+ return FALSE;
+ }
+ }
+
+ Play = (PLAYSOUNDW)GetProcAddress(hLibrary, "PlaySoundW");
+ if (Play)
+ {
+ Ret = Play(FileName, NULL, Flags);
+ }
+ FreeLibrary(hLibrary);
+ }
+
+ return Ret;
+}
+
+DWORD
+WINAPI
+PlayLogonSoundThread(
+ IN LPVOID lpParameter)
+{
+ BYTE TokenUserBuffer[256];
+ PTOKEN_USER pTokenUser = (TOKEN_USER*)TokenUserBuffer;
+ ULONG Length;
+ HKEY hKey;
+ WCHAR wszBuffer[MAX_PATH] = {0};
+ WCHAR wszDest[MAX_PATH];
+ DWORD dwSize = sizeof(wszBuffer), dwType;
+ SERVICE_STATUS_PROCESS Info;
+ UNICODE_STRING SidString;
+ NTSTATUS Status;
+ ULONG Index = 0;
+ SC_HANDLE hSCManager, hService;
+
+ /* Get SID of current user */
+ Status = NtQueryInformationToken((HANDLE)lpParameter,
+ TokenUser,
+ TokenUserBuffer,
+ sizeof(TokenUserBuffer),
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("NtQueryInformationToken failed: %x!\n", Status);
+ return 0;
+ }
+
+ /* Convert SID to string */
+ RtlInitEmptyUnicodeString(&SidString, wszBuffer, sizeof(wszBuffer));
+ Status = RtlConvertSidToUnicodeString(&SidString, pTokenUser->User.Sid, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("RtlConvertSidToUnicodeString failed: %x!\n", Status);
+ return 0;
+ }
+
+ /* Build path to logon sound registry key.
+ Note: We can't use HKCU here, because Winlogon is owned by SYSTEM user */
+ if (FAILED(StringCbCopyW(wszBuffer + SidString.Length/sizeof(WCHAR),
+ sizeof(wszBuffer) - SidString.Length,
+ L"\\AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current")))
+ {
+ /* SID is too long. Should not happen. */
+ ERR("StringCbCopyW failed!\n");
+ return 0;
+ }
+
+ /* Open registry key and query sound path */
+ if (RegOpenKeyExW(HKEY_USERS, wszBuffer, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+ {
+ ERR("RegOpenKeyExW(%ls) failed!\n", wszBuffer);
+ return 0;
+ }
+
+ if (RegQueryValueExW(hKey, NULL, NULL, &dwType,
+ (LPBYTE)wszBuffer, &dwSize) != ERROR_SUCCESS ||
+ (dwType != REG_SZ && dwType != REG_EXPAND_SZ))
+ {
+ ERR("RegQueryValueExW failed!\n");
+ RegCloseKey(hKey);
+ return 0;
+ }
+
+ RegCloseKey(hKey);
+
+ if (!wszBuffer[0])
+ {
+ /* No sound has been set */
+ ERR("No sound has been set\n");
+ return 0;
+ }
+
+ /* Expand environment variables */
+ if (!ExpandEnvironmentStringsW(wszBuffer, wszDest, MAX_PATH))
+ {
+ ERR("ExpandEnvironmentStringsW failed!\n");
+ return 0;
+ }
+
+ /* Open service manager */
+ hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+ if (!hSCManager)
+ {
+ ERR("OpenSCManager failed (%x)\n", GetLastError());
+ return 0;
+ }
+
+ /* Open wdmaud service */
+ hService = OpenServiceW(hSCManager, L"wdmaud", GENERIC_READ);
+ if (!hService)
+ {
+ /* Sound is not installed */
+ TRACE("Failed to open wdmaud service (%x)\n", GetLastError());
+ CloseServiceHandle(hSCManager);
+ return 0;
+ }
+
+ /* Wait for wdmaud start */
+ do
+ {
+ if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Info, sizeof(SERVICE_STATUS_PROCESS), &dwSize))
+ {
+ TRACE("QueryServiceStatusEx failed (%x)\n", GetLastError());
+ break;
+ }
+
+ if (Info.dwCurrentState == SERVICE_RUNNING)
+ break;
+
+ Sleep(1000);
+
+ } while (Index++ < 20);
+
+ CloseServiceHandle(hService);
+ CloseServiceHandle(hSCManager);
+
+ /* If wdmaud is not running exit */
+ if (Info.dwCurrentState != SERVICE_RUNNING)
+ {
+ WARN("wdmaud has not started!\n");
+ return 0;
+ }
+
+ /* Sound subsystem is running. Play logon sound. */
+ TRACE("Playing logon sound: %ls\n", wszDest);
+ PlaySoundRoutine(wszDest, TRUE, SND_FILENAME);
+ return 0;
+}
+
+static VOID
+PlayLogonSound(
+ IN OUT PWLSESSION Session)
+{
+ HANDLE hThread;
+
+ hThread = CreateThread(NULL, 0, PlayLogonSoundThread, (PVOID)Session->UserToken, 0, NULL);
+ if (hThread)
+ CloseHandle(hThread);
+}
+
static BOOL
HandleLogon(
IN OUT PWLSESSION Session)
{
PROFILEINFOW ProfileInfo;
- LPVOID lpEnvironment = NULL;
- BOOLEAN Old;
BOOL ret = FALSE;
/* Loading personal settings */
goto cleanup;
}
- /* Create environment block for the user */
- if (!CreateEnvironmentBlock(&lpEnvironment, Session->UserToken, TRUE))
- {
- WARN("WL: CreateEnvironmentBlock() failed\n");
- goto cleanup;
- }
-
DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGYOURPERSONALSETTINGS);
UpdatePerUserSystemParameters(0, TRUE);
goto cleanup;
}
- /* Get privilege */
- /* FIXME: who should do it? winlogon or gina? */
- /* FIXME: reverting to lower privileges after creating user shell? */
- RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old);
-
- if (!Session->Gina.Functions.WlxActivateUserShell(
- Session->Gina.Context,
- L"Default",
- NULL, /* FIXME */
- lpEnvironment))
+ if (!StartUserShell(Session))
{
//WCHAR StatusMsg[256];
WARN("WL: WlxActivateUserShell() failed\n");
WARN("WL: Failed to initialize screen saver\n");
Session->hProfileInfo = ProfileInfo.hProfile;
+
+ /* Logon has successed. Play sound. */
+ PlayLogonSound(Session);
+
ret = TRUE;
cleanup:
{
UnloadUserProfile(WLSession->UserToken, ProfileInfo.hProfile);
}
- if (lpEnvironment)
- DestroyEnvironmentBlock(lpEnvironment);
RemoveStatusMessage(Session);
if (!ret)
{
return STATUS_SUCCESS;
}
+BOOL
+WINAPI
+HandleMessageBeep(UINT uType)
+{
+ LPWSTR EventName;
+
+ switch(uType)
+ {
+ case 0xFFFFFFFF:
+ EventName = NULL;
+ break;
+ case MB_OK:
+ EventName = L"SystemDefault";
+ break;
+ case MB_ICONASTERISK:
+ EventName = L"SystemAsterisk";
+ break;
+ case MB_ICONEXCLAMATION:
+ EventName = L"SystemExclamation";
+ break;
+ case MB_ICONHAND:
+ EventName = L"SystemHand";
+ break;
+ case MB_ICONQUESTION:
+ EventName = L"SystemQuestion";
+ break;
+ default:
+ WARN("Unhandled type %d\n", uType);
+ EventName = L"SystemDefault";
+ }
+
+ return PlaySoundRoutine(EventName, FALSE, SND_ALIAS | SND_NOWAIT | SND_NOSTOP | SND_ASYNC);
+}
+
static LRESULT CALLBACK
SASWindowProc(
IN HWND hwndDlg,
}
return TRUE;
}
+ case WM_LOGONNOTIFY:
+ {
+ switch(wParam)
+ {
+ case LN_MESSAGE_BEEP:
+ {
+ return HandleMessageBeep(lParam);
+ }
+ case LN_SHELL_EXITED:
+ {
+ /* lParam is the exit code */
+ if(lParam != 1)
+ {
+ SetTimer(hwndDlg, 1, 1000, NULL);
+ }
+ break;
+ }
+ case LN_START_SCREENSAVE:
+ {
+ BOOL bSecure = FALSE;
+
+ if (inScrn)
+ break;
+
+ inScrn = TRUE;
+
+ // lParam 1 == Secure
+ if (lParam)
+ {
+ if (Session->Gina.Functions.WlxScreenSaverNotify(Session->Gina.Context, &bSecure))
+ {
+ if (bSecure) DoGenericAction(Session, WLX_SAS_ACTION_LOCK_WKSTA);
+ }
+ }
+
+ StartScreenSaver(Session);
+ inScrn = FALSE;
+ break;
+ }
+ default:
+ {
+ ERR("WM_LOGONNOTIFY case %d is unimplemented\n", wParam);
+ }
+ }
+ return 0;
+ }
+ case WM_TIMER:
+ {
+ if (wParam == 1)
+ {
+ KillTimer(hwndDlg, 1);
+ StartUserShell(Session);
+ }
+ break;
+ }
case WLX_WM_SAS:
{
DispatchSAS(Session, (DWORD)wParam);