2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winlogon
4 * FILE: base/system/winlogon/winlogon.c
6 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
8 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES *****************************************************************/
15 #include <wine/debug.h>
17 WINE_DEFAULT_DEBUG_CHANNEL(winlogon
);
19 /* GLOBALS ******************************************************************/
21 HINSTANCE hAppInstance
;
22 PWLSESSION WLSession
= NULL
;
24 /* FUNCTIONS *****************************************************************/
32 typedef BOOL (WINAPI
*PLAYSOUNDW
)(LPCWSTR
,HMODULE
,DWORD
);
33 typedef UINT (WINAPI
*WAVEOUTGETNUMDEVS
)(VOID
);
35 WAVEOUTGETNUMDEVS waveOutGetNumDevs
;
40 hLibrary
= LoadLibraryW(L
"winmm.dll");
43 waveOutGetNumDevs
= (WAVEOUTGETNUMDEVS
)GetProcAddress(hLibrary
, "waveOutGetNumDevs");
44 if (waveOutGetNumDevs
)
46 NumDevs
= waveOutGetNumDevs();
53 FreeLibrary(hLibrary
);
58 Play
= (PLAYSOUNDW
)GetProcAddress(hLibrary
, "PlaySoundW");
61 Ret
= Play(FileName
, NULL
, Flags
);
63 FreeLibrary(hLibrary
);
72 IN LPVOID lpParameter
)
75 WCHAR szBuffer
[MAX_PATH
] = {0};
76 WCHAR szDest
[MAX_PATH
];
77 DWORD dwSize
= sizeof(szBuffer
);
78 SERVICE_STATUS_PROCESS Info
;
82 if (RegOpenKeyExW(HKEY_CURRENT_USER
, L
"AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current", 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
87 if (RegQueryValueExW(hKey
, NULL
, NULL
, NULL
, (LPBYTE
)szBuffer
, &dwSize
) != ERROR_SUCCESS
)
100 szBuffer
[MAX_PATH
-1] = L
'\0';
101 if (ExpandEnvironmentStringsW(szBuffer
, szDest
, MAX_PATH
))
103 SC_HANDLE hSCManager
, hService
;
105 hSCManager
= OpenSCManager(NULL
, NULL
, SC_MANAGER_CONNECT
);
109 hService
= OpenServiceW(hSCManager
, L
"wdmaud", GENERIC_READ
);
112 CloseServiceHandle(hSCManager
);
113 TRACE("WL: failed to open sysaudio Status %x\n", GetLastError());
119 if (!QueryServiceStatusEx(hService
, SC_STATUS_PROCESS_INFO
, (LPBYTE
)&Info
, sizeof(SERVICE_STATUS_PROCESS
), &dwSize
))
121 TRACE("WL: QueryServiceStatusEx failed %x\n", GetLastError());
125 if (Info
.dwCurrentState
== SERVICE_RUNNING
)
130 }while(Index
++ < 20);
132 CloseServiceHandle(hService
);
133 CloseServiceHandle(hSCManager
);
135 if (Info
.dwCurrentState
!= SERVICE_RUNNING
)
138 PlaySoundRoutine(szDest
, TRUE
, SND_FILENAME
);
146 StartServicesManager(VOID
)
148 STARTUPINFOW StartupInfo
;
149 PROCESS_INFORMATION ProcessInformation
;
150 LPCWSTR ServiceString
= L
"services.exe";
153 /* Start the service control manager (services.exe) */
154 ZeroMemory(&StartupInfo
, sizeof(STARTUPINFOW
));
155 StartupInfo
.cb
= sizeof(StartupInfo
);
156 StartupInfo
.lpReserved
= NULL
;
157 StartupInfo
.lpDesktop
= NULL
;
158 StartupInfo
.lpTitle
= NULL
;
159 StartupInfo
.dwFlags
= 0;
160 StartupInfo
.cbReserved2
= 0;
161 StartupInfo
.lpReserved2
= 0;
163 TRACE("WL: Creating new process - %S\n", ServiceString
);
165 res
= CreateProcessW(
175 &ProcessInformation
);
178 ERR("WL: Failed to execute services (error %lu)\n", GetLastError());
182 TRACE("WL: Created new process - %S\n", ServiceString
);
184 CloseHandle(ProcessInformation
.hThread
);
185 CloseHandle(ProcessInformation
.hProcess
);
187 TRACE("WL: StartServicesManager() done.\n");
196 STARTUPINFOW StartupInfo
;
197 PROCESS_INFORMATION ProcessInformation
;
198 LPCWSTR ServiceString
= L
"lsass.exe";
201 /* Start the local security authority subsystem (lsass.exe) */
202 ZeroMemory(&StartupInfo
, sizeof(STARTUPINFOW
));
203 StartupInfo
.cb
= sizeof(StartupInfo
);
204 StartupInfo
.lpReserved
= NULL
;
205 StartupInfo
.lpDesktop
= NULL
;
206 StartupInfo
.lpTitle
= NULL
;
207 StartupInfo
.dwFlags
= 0;
208 StartupInfo
.cbReserved2
= 0;
209 StartupInfo
.lpReserved2
= 0;
211 TRACE("WL: Creating new process - %S\n", ServiceString
);
213 res
= CreateProcessW(
223 &ProcessInformation
);
225 TRACE("WL: Created new process - %S\n", ServiceString
);
227 CloseHandle(ProcessInformation
.hThread
);
228 CloseHandle(ProcessInformation
.hProcess
);
240 hEvent
= CreateEventW(NULL
,
243 L
"LSA_RPC_SERVER_ACTIVE");
246 dwError
= GetLastError();
247 TRACE("WL: Failed to create the notication event (Error %lu)\n", dwError
);
249 if (dwError
== ERROR_ALREADY_EXISTS
)
251 hEvent
= OpenEventW(SYNCHRONIZE
,
253 L
"LSA_RPC_SERVER_ACTIVE");
256 ERR("WL: Could not open the notification event (Error %lu)\n", GetLastError());
262 TRACE("WL: Wait for the LSA server!\n");
263 WaitForSingleObject(hEvent
, INFINITE
);
264 TRACE("WL: LSA server running!\n");
271 InitKeyboardLayouts()
273 WCHAR wszKeyName
[12], wszKLID
[10];
274 DWORD dwSize
= sizeof(wszKLID
), dwType
, i
;
279 /* Open registry key with preloaded layouts */
280 if (RegOpenKeyExW(HKEY_CURRENT_USER
, L
"Keyboard Layout\\Preload", 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
282 ERR("RegOpenKeyExW failed!\n");
289 /* Read values with integer names only */
290 swprintf(wszKeyName
, L
"%d", i
);
291 if (RegQueryValueExW(hKey
, wszKeyName
, NULL
, &dwType
, (LPBYTE
)wszKLID
, &dwSize
) != ERROR_SUCCESS
)
293 /* If we loaded at least one layout and there is no more
294 registry values return TRUE */
300 /* Only REG_SZ values are valid */
301 if (dwType
!= REG_SZ
)
303 ERR("Wrong type!\n");
307 /* Load keyboard layout with given locale id */
308 Flags
= KLF_SUBSTITUTE_OK
;
310 Flags
|= KLF_NOTELLSHELL
|KLF_REPLACELANG
;
312 Flags
|= KLF_ACTIVATE
; // |0x40000000
313 if (!LoadKeyboardLayoutW(wszKLID
, Flags
))
315 ERR("LoadKeyboardLayoutW failed!\n");
319 /* Move to the next entry */
323 /* Close the key now */
330 DisplayStatusMessage(
331 IN PWLSESSION Session
,
335 WCHAR StatusMsg
[MAX_PATH
];
337 if (Session
->Gina
.Version
< WLX_VERSION_1_3
)
340 if (Session
->SuppressStatus
)
343 if (LoadStringW(hAppInstance
, ResourceId
, StatusMsg
, MAX_PATH
) == 0)
346 return Session
->Gina
.Functions
.WlxDisplayStatusMessage(Session
->Gina
.Context
, hDesktop
, 0, NULL
, StatusMsg
);
351 IN PWLSESSION Session
)
353 if (Session
->Gina
.Version
< WLX_VERSION_1_3
)
356 return Session
->Gina
.Functions
.WlxRemoveStatusMessage(Session
->Gina
.Context
);
359 static INT_PTR CALLBACK
360 GinaLoadFailedWindowProc(
370 switch (LOWORD(wParam
))
373 EndDialog(hwndDlg
, IDOK
);
381 WCHAR templateText
[MAX_PATH
], text
[MAX_PATH
];
383 len
= GetDlgItemTextW(hwndDlg
, IDC_GINALOADFAILED
, templateText
, MAX_PATH
);
386 wsprintfW(text
, templateText
, (LPWSTR
)lParam
);
387 SetDlgItemTextW(hwndDlg
, IDC_GINALOADFAILED
, text
);
389 SetFocus(GetDlgItem(hwndDlg
, IDOK
));
394 EndDialog(hwndDlg
, IDCANCEL
);
404 IN HINSTANCE hInstance
,
405 IN HINSTANCE hPrevInstance
,
410 LSA_STRING ProcessName
, PackageName
;
412 LSA_OPERATIONAL_MODE Mode
;
414 ULONG AuthenticationPackage
;
417 ULONG HardErrorResponse
;
421 UNREFERENCED_PARAMETER(hPrevInstance
);
422 UNREFERENCED_PARAMETER(lpCmdLine
);
423 UNREFERENCED_PARAMETER(nShowCmd
);
425 hAppInstance
= hInstance
;
427 if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE
))
429 ERR("WL: Could not register logon process\n");
430 NtShutdownSystem(ShutdownNoReboot
);
434 WLSession
= (PWLSESSION
)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION
));
437 ERR("WL: Could not allocate memory for winlogon instance\n");
438 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
441 ZeroMemory(WLSession
, sizeof(WLSESSION
));
442 WLSession
->DialogTimeout
= 120; /* 2 minutes */
444 if (!CreateWindowStationAndDesktops(WLSession
))
446 ERR("WL: Could not create window station and desktops\n");
447 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
450 LockWorkstation(WLSession
);
452 /* Load default keyboard layouts */
453 if (!InitKeyboardLayouts())
455 ERR("WL: Could not preload keyboard layouts\n");
456 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
460 if (!StartServicesManager())
462 ERR("WL: Could not start services.exe\n");
463 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, NULL
, OptionOk
, &HardErrorResponse
);
469 ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
470 NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
, 0, 0, 0, OptionOk
, &HardErrorResponse
);
474 /* Load and initialize gina */
475 if (!GinaInit(WLSession
))
477 ERR("WL: Failed to initialize Gina\n");
478 DialogBoxParam(hAppInstance
, MAKEINTRESOURCE(IDD_GINALOADFAILED
), GetDesktopWindow(), GinaLoadFailedWindowProc
, (LPARAM
)L
"");
479 HandleShutdown(WLSession
, WLX_SAS_ACTION_SHUTDOWN_REBOOT
);
483 DisplayStatusMessage(WLSession
, WLSession
->WinlogonDesktop
, IDS_REACTOSISSTARTINGUP
);
486 /* Wait for the LSA server */
490 /* Connect to NetLogon service (lsass.exe) */
491 /* Real winlogon uses "Winlogon" */
492 RtlInitUnicodeString((PUNICODE_STRING
)&ProcessName
, L
"Winlogon");
493 Status
= LsaRegisterLogonProcess(&ProcessName
, &LsaHandle
, &Mode
);
494 if (Status
== STATUS_PORT_CONNECTION_REFUSED
)
496 /* Add the 'SeTcbPrivilege' privilege and try again */
497 Status
= RtlAdjustPrivilege(SE_TCB_PRIVILEGE
, TRUE
, TRUE
, &Old
);
498 if (!NT_SUCCESS(Status
))
500 ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status
));
503 Status
= LsaRegisterLogonProcess(&ProcessName
, &LsaHandle
, &Mode
);
505 if (!NT_SUCCESS(Status
))
507 ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status
));
511 RtlInitUnicodeString((PUNICODE_STRING
)&PackageName
, MICROSOFT_KERBEROS_NAME_W
);
512 Status
= LsaLookupAuthenticationPackage(LsaHandle
, &PackageName
, &AuthenticationPackage
);
513 if (!NT_SUCCESS(Status
))
515 ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status
));
516 LsaDeregisterLogonProcess(LsaHandle
);
521 /* Create a hidden window to get SAS notifications */
522 if (!InitializeSAS(WLSession
))
524 ERR("WL: Failed to initialize SAS\n");
528 //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS);
529 //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS);
531 /* Display logged out screen */
532 WLSession
->LogonStatus
= WKSTA_IS_LOGGED_OFF
;
533 RemoveStatusMessage(WLSession
);
535 /* Check for pending setup */
536 if (GetSetupType() != 0)
538 TRACE("WL: Setup mode detected\n");
540 /* Run setup and reboot when done */
541 SwitchDesktop(WLSession
->ApplicationDesktop
);
545 PostMessageW(WLSession
->SASWindow
, WLX_WM_SAS
, WLX_SAS_TYPE_TIMEOUT
, 0);
547 /* Play logon sound */
548 hThread
= CreateThread(NULL
, 0, PlayLogonSoundThread
, NULL
, 0, NULL
);
551 CloseHandle(hThread
);
554 /* Tell kernel that CurrentControlSet is good (needed
555 * to support Last good known configuration boot) */
556 NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED
| 1);
558 /* Message loop for the SAS window */
559 while (GetMessageW(&Msg
, WLSession
->SASWindow
, 0, 0))
561 TranslateMessage(&Msg
);
562 DispatchMessageW(&Msg
);
565 /* We never go there */