update for HEAD-2003091401
[reactos.git] / subsys / system / winlogon / winlogon.c
1 /* $Id$
2  * 
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            services/winlogon/winlogon.c
6  * PURPOSE:         Logon 
7  * PROGRAMMER:      David Welch (welch@cwcom.net)
8  * UPDATE HISTORY:
9  *                  Created 22/05/98
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntos.h>
15 #include <windows.h>
16 #include <stdio.h>
17 #include <lsass/ntsecapi.h>
18 #include <wchar.h>
19
20 #include "setup.h"
21
22 #define NDEBUG
23 #include <debug.h>
24
25 /* GLOBALS ******************************************************************/
26
27 HWINSTA InteractiveWindowStation;   /* WinSta0 */
28 HDESK ApplicationDesktop;           /* WinSta0\Default */
29 HDESK WinlogonDesktop;              /* WinSta0\Winlogon */
30 HDESK ScreenSaverDesktop;           /* WinSta0\Screen-Saver */
31
32 /* FUNCTIONS *****************************************************************/
33
34 static void PrintString (char* fmt,...)
35 {
36    char buffer[512];
37    va_list ap;
38
39    va_start(ap, fmt);
40    vsprintf(buffer, fmt, ap);
41    va_end(ap);
42
43    OutputDebugString(buffer);
44 }
45
46
47 static BOOLEAN StartServices(VOID)
48 {
49    HANDLE ServicesInitEvent;
50    BOOLEAN Result;
51    STARTUPINFO StartupInfo;
52    PROCESS_INFORMATION ProcessInformation;
53    CHAR CommandLine[MAX_PATH];
54    DWORD Count;
55
56    /* Start the service control manager (services.exe) */   
57    GetSystemDirectory(CommandLine, MAX_PATH);
58    strcat(CommandLine, "\\services.exe");
59       
60    StartupInfo.cb = sizeof(StartupInfo);
61    StartupInfo.lpReserved = NULL;
62    StartupInfo.lpDesktop = NULL;
63    StartupInfo.lpTitle = NULL;
64    StartupInfo.dwFlags = 0;
65    StartupInfo.cbReserved2 = 0;
66    StartupInfo.lpReserved2 = 0;
67
68 #if 0   
69    PrintString("WL: Creating new process - \"services.exe\".\n");
70 #endif
71
72    Result = CreateProcess(CommandLine,
73                           NULL,
74                           NULL,
75                           NULL,
76                           FALSE,
77                           DETACHED_PROCESS,
78                           NULL,
79                           NULL,
80                           &StartupInfo,
81                           &ProcessInformation);
82    if (!Result)
83      {
84         PrintString("WL: Failed to execute services\n");
85         return FALSE;
86      }
87    
88    /* wait for event creation (by SCM) for max. 20 seconds */
89    for (Count = 0; Count < 20; Count++)
90      {
91         Sleep(1000);
92    
93         //DbgPrint("WL: Attempting to open event \"SvcctrlStartEvent_A3725DX\"\n");
94         ServicesInitEvent = OpenEvent(EVENT_ALL_ACCESS, //SYNCHRONIZE,
95                                       FALSE,
96                                       "SvcctrlStartEvent_A3725DX");
97         if (ServicesInitEvent != NULL)
98           {
99              break;
100           }
101      }
102    
103    if (ServicesInitEvent == NULL)
104      {
105         DbgPrint("WL: Failed to open event \"SvcctrlStartEvent_A3725DX\"\n");
106         return FALSE;
107      }
108
109    /* wait for event signalization */
110    //DbgPrint("WL: Waiting forever on event handle: %x\n", ServicesInitEvent);
111    WaitForSingleObject(ServicesInitEvent, INFINITE);
112    //DbgPrint("WL: Closing event object \"SvcctrlStartEvent_A3725DX\"\n");
113    CloseHandle(ServicesInitEvent);
114    //DbgPrint("WL: StartServices() Done.\n");
115       
116    return TRUE;
117 }
118
119 static BOOLEAN StartLsass(VOID)
120 {
121    HANDLE LsassInitEvent;
122    BOOLEAN Result;
123    STARTUPINFO StartupInfo;
124    PROCESS_INFORMATION ProcessInformation;
125    CHAR CommandLine[MAX_PATH];
126    
127    LsassInitEvent = CreateEvent(NULL,
128                                 TRUE,
129                                 FALSE,
130                                 "\\LsassInitDone");
131    
132    if (LsassInitEvent == NULL)
133      {
134         DbgPrint("WL: Failed to create lsass notification event\n");
135         return(FALSE);
136      }
137    
138    /* Start the local security authority subsystem (lsass.exe) */
139    
140    GetSystemDirectory(CommandLine, MAX_PATH);
141    strcat(CommandLine, "\\lsass.exe");
142    
143    StartupInfo.cb = sizeof(StartupInfo);
144    StartupInfo.lpReserved = NULL;
145    StartupInfo.lpDesktop = NULL;
146    StartupInfo.lpTitle = NULL;
147    StartupInfo.dwFlags = 0;
148    StartupInfo.cbReserved2 = 0;
149    StartupInfo.lpReserved2 = 0;
150    
151    Result = CreateProcess(CommandLine,
152                           NULL,
153                           NULL,
154                           NULL,
155                           FALSE,
156                           DETACHED_PROCESS,
157                           NULL,
158                           NULL,
159                           &StartupInfo,
160                           &ProcessInformation);
161    if (!Result)
162      {
163         DbgPrint("WL: Failed to execute lsass\n");
164         return(FALSE);
165      }
166    
167    DPRINT("WL: Waiting for lsass\n");
168    WaitForSingleObject(LsassInitEvent, INFINITE);
169    CloseHandle(LsassInitEvent);
170    
171    return(TRUE);
172 }
173
174 static BOOLEAN OpenRegistryKey(HANDLE *WinLogonKey)
175 {
176    return ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
177                                         _T("SOFTWARE\\ReactOS\\Windows NT\\CurrentVersion\\WinLogon"),
178                                         0,
179                                         KEY_QUERY_VALUE,
180                                         WinLogonKey);
181 }
182
183 static BOOLEAN StartProcess(PCHAR ValueName)
184 {
185    BOOL StartIt;
186    HANDLE WinLogonKey;
187    DWORD Type;
188    DWORD Size;
189    DWORD StartValue;
190
191    StartIt = TRUE;
192    if (OpenRegistryKey(&WinLogonKey))
193      {
194         Size = sizeof(DWORD);
195         if (ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
196                                              ValueName,
197                                              NULL,
198                                              &Type,
199                                              (LPBYTE) &StartValue,
200                                              &Size))
201            {
202            if (REG_DWORD == Type)
203              {
204                 StartIt = (0 != StartValue);
205              }
206            }
207         RegCloseKey(WinLogonKey);
208      }
209
210    return StartIt;
211 }
212
213 static PCHAR GetShell(PCHAR CommandLine)
214 {
215    HANDLE WinLogonKey;
216    BOOL GotCommandLine;
217    DWORD Type;
218    DWORD Size;
219    CHAR Shell[_MAX_PATH];
220
221    GotCommandLine = FALSE;
222    if (OpenRegistryKey(&WinLogonKey))
223      {
224         Size = MAX_PATH;
225         if (ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
226                                              _T("Shell"),
227                                              NULL,
228                                              &Type,
229                                              (LPBYTE) Shell,
230                                              &Size))
231            {
232            if (REG_EXPAND_SZ == Type)
233              {
234                 ExpandEnvironmentStrings(Shell, CommandLine, _MAX_PATH);
235                 GotCommandLine = TRUE;
236              }
237            else if (REG_SZ == Type)
238              {
239                 strcpy(CommandLine, Shell);
240                 GotCommandLine = TRUE;
241              }
242            }
243         RegCloseKey(WinLogonKey);
244      }
245
246    if (! GotCommandLine)
247      {
248         GetSystemDirectory(CommandLine, MAX_PATH - 10);
249         strcat(CommandLine, "\\cmd.exe");
250      }
251
252    return CommandLine;
253 }
254
255 static BOOL DoLoginUser(PCHAR Name, PCHAR Password)
256 {
257    PROCESS_INFORMATION ProcessInformation;
258    STARTUPINFO StartupInfo;
259    BOOLEAN Result;
260    CHAR CommandLine[MAX_PATH];
261    CHAR CurrentDirectory[MAX_PATH];
262
263    GetWindowsDirectory(CurrentDirectory, MAX_PATH);
264
265    StartupInfo.cb = sizeof(StartupInfo);
266    StartupInfo.lpReserved = NULL;
267    StartupInfo.lpDesktop = NULL;
268    StartupInfo.lpTitle = NULL;
269    StartupInfo.dwFlags = 0;
270    StartupInfo.cbReserved2 = 0;
271    StartupInfo.lpReserved2 = 0;
272    
273    Result = CreateProcess(NULL,
274                           GetShell(CommandLine),
275                           NULL,
276                           NULL,
277                           FALSE,
278                           DETACHED_PROCESS,
279                           NULL,
280                           CurrentDirectory,
281                           &StartupInfo,
282                           &ProcessInformation);
283    if (!Result)
284      {
285         DbgPrint("WL: Failed to execute user shell %s\n", CommandLine);
286         return FALSE;
287      }
288    WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
289    CloseHandle( ProcessInformation.hProcess );
290    CloseHandle( ProcessInformation.hThread );
291
292    return TRUE;
293 }
294
295 int STDCALL
296 WinMain(HINSTANCE hInstance,
297         HINSTANCE hPrevInstance,
298         LPSTR lpCmdLine,
299         int nShowCmd)
300 {
301 #if 0
302   LSA_STRING ProcessName;
303   NTSTATUS Status;
304   HANDLE LsaHandle;
305   LSA_OPERATIONAL_MODE Mode;
306 #endif
307   CHAR LoginPrompt[] = "login:";
308   CHAR PasswordPrompt[] = "password:";
309   DWORD Result;
310   CHAR LoginName[255];
311   CHAR Password[255];
312   BOOL Success;
313   ULONG i;
314   NTSTATUS Status;
315   
316   /*
317    * FIXME: Create a security descriptor with
318    *        one ACE containing the Winlogon SID
319    */
320   
321   /*
322    * Create the interactive window station
323    */
324    InteractiveWindowStation = 
325      CreateWindowStationW(L"WinSta0", 0, GENERIC_ALL, NULL);
326    if (InteractiveWindowStation == NULL)
327      {
328        DbgPrint("WL: Failed to create window station (0x%X)\n", GetLastError());
329        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, 0, 0, 0);
330        ExitProcess(1);
331      }
332    
333    /*
334     * Set the process window station
335     */
336    SetProcessWindowStation(InteractiveWindowStation);
337
338    /*
339     * Create the application desktop
340     */
341    ApplicationDesktop = 
342      CreateDesktopW(L"Default",
343                     NULL,
344                     NULL,
345                     0,      /* FIXME: Set some flags */
346                     GENERIC_ALL,
347                     NULL); 
348
349    /*
350     * Create the winlogon desktop
351     */
352    WinlogonDesktop = CreateDesktopW(L"Winlogon",
353                                     NULL,
354                                     NULL,
355                                     0,      /* FIXME: Set some flags */
356                                     GENERIC_ALL,
357                                     NULL);  
358    
359    /*
360     * Create the screen saver desktop
361     */
362    ScreenSaverDesktop = CreateDesktopW(L"Screen-Saver",
363                                        NULL,
364                                        NULL,
365                                        0,      /* FIXME: Set some flags */
366                                        GENERIC_ALL,
367                                        NULL);  
368    
369    /*
370     * Switch to winlogon desktop
371     */
372    /* FIXME: Do start up in the application desktop for now. */
373    Status = NtSetInformationProcess(NtCurrentProcess(),
374                                     ProcessDesktop,
375                                     &ApplicationDesktop,
376                                     sizeof(ApplicationDesktop));
377    if (!NT_SUCCESS(Status))
378      {
379        DbgPrint("WL: Cannot set default desktop for winlogon.\n");
380      }
381    SetThreadDesktop(ApplicationDesktop);
382    Success = SwitchDesktop(ApplicationDesktop);
383    if (!Success)
384      {
385        DbgPrint("WL: Cannot switch to Winlogon desktop (0x%X)\n", GetLastError());
386      }
387
388    AllocConsole();
389    SetConsoleTitle( "Winlogon" );
390
391   /* Check for pending setup */
392   if (GetSetupType () != 0)
393     {
394       DPRINT ("Winlogon: CheckForSetup() in setup mode\n");
395
396       /* Run setup and reboot when done */
397       RunSetup ();
398
399 //      NtShutdownSystem (ShutdownReboot);
400       NtShutdownSystem (ShutdownNoReboot);
401       ExitProcess (0);
402       return 0;
403     }
404
405    /* start system processes (services.exe & lsass.exe) */
406    if (StartProcess("StartServices"))
407      {
408         if (!StartServices())
409           {
410              DbgPrint("WL: Failed to start Services (0x%X)\n", GetLastError());
411           }
412      }
413 #if 0
414    if (StartProcess("StartLsass"))
415      {
416         if (!StartLsass())
417           {
418              DbgPrint("WL: Failed to start LSASS (0x%X)\n", GetLastError());
419           }
420      }
421 #endif
422    
423    /* FIXME: What name does the real WinLogon use? */
424 #if 0
425    RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"WinLogon");
426    Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
427    if (!NT_SUCCESS(Status))
428      {
429         DbgPrint("WL: Failed to connect to LSASS\n");
430         return(1);
431      }
432 #endif
433    
434    /* FIXME: Create a window class and associate a Winlogon
435     *        window procedure with it.
436     *        Register SAS with the window.
437     *        Register for logoff notification
438     */
439    
440    /* Main loop */
441 #if 0
442    /* Display login prompt */
443    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
444                 LoginPrompt,
445                 strlen(LoginPrompt),  // wcslen(LoginPrompt),
446                 &Result,
447                 NULL);
448    i = 0;
449    do
450      {
451        ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
452                    &LoginName[i],
453                    1,
454                    &Result,
455                    NULL);
456        i++;
457      } while (LoginName[i - 1] != '\n');
458    LoginName[i - 1] = 0;
459        
460    /* Display password prompt */
461    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
462                 PasswordPrompt,
463                 strlen(PasswordPrompt),  // wcslen(PasswordPrompt),
464                 &Result,
465                 NULL);
466    i = 0;
467    do
468      {
469        ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
470                    &Password[i],
471                    1,
472                    &Result,
473                    NULL);
474        i++;
475      } while (Password[i - 1] != '\n');
476    Password[i - 1] =0;
477 #endif
478
479    if (! DoLoginUser(LoginName, Password))
480      {
481      }
482
483    NtShutdownSystem(ShutdownNoReboot);
484    
485    ExitProcess(0);
486    
487    return 0;
488 }