SM: init system reading the registry
[reactos.git] / reactos / subsys / csrss / init.c
1 /* $Id$
2 *
3 * reactos/subsys/csrss/init.c
4 *
5 * Initialize the CSRSS subsystem server process.
6 *
7 * ReactOS Operating System
8 *
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <csrss/csrss.h>
14 #include <ddk/ntddk.h>
15 #include <ntdll/csr.h>
16 #include <ntdll/rtl.h>
17 #include <ntdll/ldr.h>
18 #include <win32k/win32k.h>
19 #include <rosrtl/string.h>
20 #include <sm/helper.h>
21
22 #include "api.h"
23 #include "csrplugin.h"
24
25 #define NDEBUG
26 #include <debug.h>
27
28 /* GLOBALS ******************************************************************/
29
30 HANDLE CsrHeap = (HANDLE) 0;
31
32 HANDLE CsrObjectDirectory = (HANDLE) 0;
33
34 UNICODE_STRING CsrDirectoryName;
35
36 extern HANDLE CsrssApiHeap;
37
38 static unsigned InitCompleteProcCount;
39 static CSRPLUGIN_INIT_COMPLETE_PROC *InitCompleteProcs = NULL;
40
41 HANDLE hSbApiPort = (HANDLE) 0;
42
43 HANDLE hBootstrapOk = (HANDLE) 0;
44
45 HANDLE hSmApiPort = (HANDLE) 0;
46
47 HANDLE hApiPort = (HANDLE) 0;
48
49 /**********************************************************************
50 * CsrpAddInitCompleteProc/1
51 */
52 static NTSTATUS FASTCALL
53 CsrpAddInitCompleteProc(CSRPLUGIN_INIT_COMPLETE_PROC Proc)
54 {
55 CSRPLUGIN_INIT_COMPLETE_PROC *NewProcs;
56
57 DPRINT("CSR: %s called\n", __FUNCTION__);
58
59 NewProcs = RtlAllocateHeap(CsrssApiHeap, 0,
60 (InitCompleteProcCount + 1)
61 * sizeof(CSRPLUGIN_INIT_COMPLETE_PROC));
62 if (NULL == NewProcs)
63 {
64 return STATUS_NO_MEMORY;
65 }
66 if (0 != InitCompleteProcCount)
67 {
68 RtlCopyMemory(NewProcs, InitCompleteProcs,
69 InitCompleteProcCount * sizeof(CSRPLUGIN_INIT_COMPLETE_PROC));
70 RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
71 }
72 NewProcs[InitCompleteProcCount] = Proc;
73 InitCompleteProcs = NewProcs;
74 InitCompleteProcCount++;
75
76 return STATUS_SUCCESS;
77 }
78
79 /**********************************************************************
80 * CallInitComplete/0
81 */
82 static BOOL FASTCALL
83 CallInitComplete(void)
84 {
85 BOOL Ok;
86 unsigned i;
87
88 DPRINT("CSR: %s called\n", __FUNCTION__);
89
90 Ok = TRUE;
91 if (0 != InitCompleteProcCount)
92 {
93 for (i = 0; i < InitCompleteProcCount && Ok; i++)
94 {
95 Ok = (*(InitCompleteProcs[i]))();
96 }
97 RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
98 }
99
100 return Ok;
101 }
102
103 ULONG
104 InitializeVideoAddressSpace(VOID);
105
106 /**********************************************************************
107 * CsrpParseCommandLine/2
108 */
109 static NTSTATUS
110 CsrpParseCommandLine (
111 ULONG ArgumentCount,
112 PWSTR *ArgumentArray
113 )
114 {
115 NTSTATUS Status;
116 OBJECT_ATTRIBUTES Attributes;
117
118 DPRINT("CSR: %s called\n", __FUNCTION__);
119
120
121 /* DbgPrint ("Arguments: %ld\n", ArgumentCount);
122 for (i = 0; i < ArgumentCount; i++)
123 {
124 DbgPrint ("Argument %ld: %S\n", i, ArgumentArray[i]);
125 }*/
126
127
128 /* create object directory ('\Windows') */
129 RtlCreateUnicodeString (&CsrDirectoryName,
130 L"\\Windows");
131
132 InitializeObjectAttributes (&Attributes,
133 &CsrDirectoryName,
134 0,
135 NULL,
136 NULL);
137
138 Status = NtCreateDirectoryObject(&CsrObjectDirectory,
139 0xF000F, /* ea:??? */
140 &Attributes);
141
142 return Status;
143 }
144
145 /**********************************************************************
146 * CsrpInitVideo/0
147 *
148 * TODO: we need a virtual device for sessions other than
149 * TODO: the console one
150 */
151 static NTSTATUS
152 CsrpInitVideo (ULONG argc, PWSTR* argv)
153 {
154 OBJECT_ATTRIBUTES ObjectAttributes;
155 UNICODE_STRING DeviceName;
156 IO_STATUS_BLOCK Iosb;
157 HANDLE VideoHandle = (HANDLE) 0;
158 NTSTATUS Status = STATUS_SUCCESS;
159
160 DPRINT("CSR: %s called\n", __FUNCTION__);
161
162 InitializeVideoAddressSpace();
163
164 RtlRosInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\DISPLAY1");
165 InitializeObjectAttributes(&ObjectAttributes,
166 &DeviceName,
167 0,
168 NULL,
169 NULL);
170 Status = NtOpenFile(&VideoHandle,
171 FILE_ALL_ACCESS,
172 &ObjectAttributes,
173 &Iosb,
174 0,
175 0);
176 if (NT_SUCCESS(Status))
177 {
178 NtClose(VideoHandle);
179 }
180 return Status;
181 }
182
183 /**********************************************************************
184 * CsrpInitWin32Csr/0
185 *
186 * TODO: this function should be turned more general to load an
187 * TODO: hosted server DLL as received from the command line;
188 * TODO: for instance: ServerDll=winsrv:ConServerDllInitialization,2
189 * TODO: ^method ^dll ^api ^sid
190 * TODO:
191 * TODO: CsrpHostServerDll (LPWSTR DllName,
192 * TODO: LPWSTR ApiName,
193 * TODO: DWORD ServerId)
194 */
195 static NTSTATUS
196 CsrpInitWin32Csr (ULONG argc, PWSTR* argv)
197 {
198 NTSTATUS Status;
199 UNICODE_STRING DllName;
200 HINSTANCE hInst;
201 ANSI_STRING ProcName;
202 CSRPLUGIN_INITIALIZE_PROC InitProc;
203 CSRSS_EXPORTED_FUNCS Exports;
204 PCSRSS_API_DEFINITION ApiDefinitions;
205 PCSRSS_OBJECT_DEFINITION ObjectDefinitions;
206 CSRPLUGIN_INIT_COMPLETE_PROC InitCompleteProc;
207
208 DPRINT("CSR: %s called\n", __FUNCTION__);
209
210 RtlInitUnicodeString(&DllName, L"win32csr.dll");
211 Status = LdrLoadDll(NULL, 0, &DllName, (PVOID *) &hInst);
212 if (! NT_SUCCESS(Status))
213 {
214 return Status;
215 }
216 RtlInitAnsiString(&ProcName, "Win32CsrInitialization");
217 Status = LdrGetProcedureAddress(hInst, &ProcName, 0, (PVOID *) &InitProc);
218 if (! NT_SUCCESS(Status))
219 {
220 return Status;
221 }
222 Exports.CsrInsertObjectProc = CsrInsertObject;
223 Exports.CsrGetObjectProc = CsrGetObject;
224 Exports.CsrReleaseObjectProc = CsrReleaseObject;
225 if (! (*InitProc)(&ApiDefinitions, &ObjectDefinitions, &InitCompleteProc,
226 &Exports, CsrssApiHeap))
227 {
228 return STATUS_UNSUCCESSFUL;
229 }
230
231 Status = CsrApiRegisterDefinitions(ApiDefinitions);
232 if (! NT_SUCCESS(Status))
233 {
234 return Status;
235 }
236 Status = CsrRegisterObjectDefinitions(ObjectDefinitions);
237 if (! NT_SUCCESS(Status))
238 {
239 return Status;
240 }
241 if (NULL != InitCompleteProc)
242 {
243 Status = CsrpAddInitCompleteProc(InitCompleteProc);
244 }
245
246 return Status;
247 }
248
249 CSRSS_API_DEFINITION NativeDefinitions[] =
250 {
251 CSRSS_DEFINE_API(CSRSS_CREATE_PROCESS, CsrCreateProcess),
252 CSRSS_DEFINE_API(CSRSS_TERMINATE_PROCESS, CsrTerminateProcess),
253 CSRSS_DEFINE_API(CSRSS_CONNECT_PROCESS, CsrConnectProcess),
254 CSRSS_DEFINE_API(CSRSS_REGISTER_SERVICES_PROCESS, CsrRegisterServicesProcess),
255 CSRSS_DEFINE_API(CSRSS_GET_SHUTDOWN_PARAMETERS, CsrGetShutdownParameters),
256 CSRSS_DEFINE_API(CSRSS_SET_SHUTDOWN_PARAMETERS, CsrSetShutdownParameters),
257 CSRSS_DEFINE_API(CSRSS_GET_INPUT_HANDLE, CsrGetInputHandle),
258 CSRSS_DEFINE_API(CSRSS_GET_OUTPUT_HANDLE, CsrGetOutputHandle),
259 CSRSS_DEFINE_API(CSRSS_CLOSE_HANDLE, CsrCloseHandle),
260 CSRSS_DEFINE_API(CSRSS_VERIFY_HANDLE, CsrVerifyHandle),
261 CSRSS_DEFINE_API(CSRSS_DUPLICATE_HANDLE, CsrDuplicateHandle),
262 CSRSS_DEFINE_API(CSRSS_GET_INPUT_WAIT_HANDLE, CsrGetInputWaitHandle),
263 { 0, 0, 0, NULL }
264 };
265
266 static NTSTATUS STDCALL
267 CsrpCreateListenPort (IN LPWSTR Name,
268 IN OUT PHANDLE Port,
269 IN PTHREAD_START_ROUTINE ListenThread)
270 {
271 NTSTATUS Status = STATUS_SUCCESS;
272 OBJECT_ATTRIBUTES PortAttributes;
273 UNICODE_STRING PortName;
274
275 DPRINT("CSR: %s called\n", __FUNCTION__);
276
277 RtlInitUnicodeString (& PortName, Name);
278 InitializeObjectAttributes (& PortAttributes,
279 & PortName,
280 0,
281 NULL,
282 NULL);
283 Status = NtCreatePort ( Port,
284 & PortAttributes,
285 260, /* TODO: make caller set it*/
286 328, /* TODO: make caller set it*/
287 0); /* TODO: make caller set it*/
288 if(!NT_SUCCESS(Status))
289 {
290 DPRINT1("CSR: %s: NtCreatePort failed (Status=%08lx)\n",
291 __FUNCTION__, Status);
292 return Status;
293 }
294 Status = RtlCreateUserThread(NtCurrentProcess(),
295 NULL,
296 FALSE,
297 0,
298 NULL,
299 NULL,
300 (PTHREAD_START_ROUTINE) ListenThread,
301 Port,
302 NULL,
303 NULL);
304 return Status;
305 }
306
307 /* === INIT ROUTINES === */
308
309 /**********************************************************************
310 * CsrpCreateCallbackPort/0
311 */
312 static NTSTATUS
313 CsrpCreateHeap (ULONG argc, PWSTR* argv)
314 {
315 DPRINT("CSR: %s called\n", __FUNCTION__);
316
317 CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE,
318 NULL,
319 65536,
320 65536,
321 NULL,
322 NULL);
323 if (CsrssApiHeap == NULL)
324 {
325 return STATUS_UNSUCCESSFUL;
326 }
327 return STATUS_SUCCESS;
328 }
329
330 /**********************************************************************
331 * CsrpCreateCallbackPort/0
332 */
333 static NTSTATUS
334 CsrpCreateCallbackPort (ULONG argc, PWSTR* argv)
335 {
336 DPRINT("CSR: %s called\n", __FUNCTION__);
337
338 return CsrpCreateListenPort (L"\\Windows\\SbApiPort",
339 & hSbApiPort,
340 ServerSbApiPortThread);
341 }
342
343 /**********************************************************************
344 * CsrpRegisterSubsystem/2
345 */
346 static NTSTATUS
347 CsrpRegisterSubsystem (ULONG argc, PWSTR* argv)
348 {
349 NTSTATUS Status = STATUS_SUCCESS;
350 OBJECT_ATTRIBUTES BootstrapOkAttributes;
351 UNICODE_STRING Name;
352
353 DPRINT("CSR: %s called\n", __FUNCTION__);
354
355 /*
356 * Create the event object the callback port
357 * thread will signal *if* the SM will
358 * authorize us to bootstrap.
359 */
360 RtlInitUnicodeString (& Name, L"\\CsrssBooting");
361 InitializeObjectAttributes(& BootstrapOkAttributes,
362 & Name,
363 0, NULL, NULL);
364 Status = NtCreateEvent (& hBootstrapOk,
365 EVENT_ALL_ACCESS,
366 & BootstrapOkAttributes,
367 SynchronizationEvent,
368 FALSE);
369 if(!NT_SUCCESS(Status))
370 {
371 DPRINT("CSR: %s: NtCreateEvent failed (Status=0x%08lx)\n",
372 __FUNCTION__, Status);
373 return Status;
374 }
375 /*
376 * Let's tell the SM a new environment
377 * subsystem server is in the system.
378 */
379 RtlInitUnicodeString (& Name, L"\\Windows\\SbApiPort");
380 DPRINT("CSR: %s: registering with SM for\n IMAGE_SUBSYSTEM_WINDOWS_CUI == 3\n", __FUNCTION__);
381 Status = SmConnectApiPort (& Name,
382 hSbApiPort,
383 IMAGE_SUBSYSTEM_WINDOWS_CUI,
384 & hSmApiPort);
385 if(!NT_SUCCESS(Status))
386 {
387 DPRINT("CSR: %s unable to connect to the SM (Status=0x%08lx)\n",
388 __FUNCTION__, Status);
389 NtClose (hBootstrapOk);
390 return Status;
391 }
392 /*
393 * Wait for SM to reply OK... If the SM
394 * won't answer, we hang here forever!
395 */
396 DPRINT("CSR: %s: waiting for SM to OK boot...\n", __FUNCTION__);
397 Status = NtWaitForSingleObject (hBootstrapOk,
398 FALSE,
399 NULL);
400 NtClose (hBootstrapOk);
401 return Status;
402 }
403
404 /**********************************************************************
405 * CsrpCreateApiPort/0
406 */
407 static NTSTATUS
408 CsrpCreateApiPort (ULONG argc, PWSTR* argv)
409 {
410 DPRINT("CSR: %s called\n", __FUNCTION__);
411
412 return CsrpCreateListenPort (L"\\Windows\\ApiPort",
413 & hApiPort,
414 ServerApiPortThread);
415 }
416
417 /**********************************************************************
418 * CsrpApiRegisterDef/0
419 */
420 static NTSTATUS
421 CsrpApiRegisterDef (ULONG argc, PWSTR* argv)
422 {
423 return CsrApiRegisterDefinitions(NativeDefinitions);
424 }
425
426 /**********************************************************************
427 * CsrpCCTS/2
428 */
429 static NTSTATUS
430 CsrpCCTS (ULONG argc, PWSTR* argv)
431 {
432 return CsrClientConnectToServer();
433 }
434
435 /**********************************************************************
436 * CsrpRunWinlogon/0
437 *
438 * Start the logon process (winlogon.exe).
439 *
440 * TODO: this should be moved in CsrpCreateSession/x (one per session)
441 * TODO: in its own desktop (one logon desktop per winstation).
442 */
443 static NTSTATUS
444 CsrpRunWinlogon (ULONG argc, PWSTR* argv)
445 {
446 NTSTATUS Status = STATUS_SUCCESS;
447 UNICODE_STRING ImagePath;
448 UNICODE_STRING CommandLine;
449 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
450 RTL_PROCESS_INFO ProcessInfo;
451
452
453 DPRINT("CSR: %s called\n", __FUNCTION__);
454
455 /* initialize the process parameters */
456 RtlInitUnicodeString (& ImagePath, L"\\SystemRoot\\system32\\winlogon.exe");
457 RtlInitUnicodeString (& CommandLine, L"");
458 RtlCreateProcessParameters(& ProcessParameters,
459 & ImagePath,
460 NULL,
461 NULL,
462 & CommandLine,
463 NULL,
464 NULL,
465 NULL,
466 NULL,
467 NULL);
468 /* Create the winlogon process */
469 Status = RtlCreateUserProcess (& ImagePath,
470 OBJ_CASE_INSENSITIVE,
471 ProcessParameters,
472 NULL,
473 NULL,
474 NULL,
475 FALSE,
476 NULL,
477 NULL,
478 & ProcessInfo);
479 /* Cleanup */
480 RtlDestroyProcessParameters (ProcessParameters);
481 if (!NT_SUCCESS(Status))
482 {
483 DPRINT("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
484 __FUNCTION__, Status);
485 }
486 return Status;
487 }
488
489
490
491 typedef NTSTATUS (* CSR_INIT_ROUTINE)(ULONG, PWSTR*);
492
493 struct {
494 BOOL Required;
495 CSR_INIT_ROUTINE EntryPoint;
496 PCHAR ErrorMessage;
497 } InitRoutine [] = {
498 {TRUE, CsrpCreateCallbackPort, "create the callback port \\Windows\\SbApiPort"},
499 {TRUE, CsrpRegisterSubsystem, "register with SM"},
500 {TRUE, CsrpCreateHeap, "create the CSR heap"},
501 {TRUE, CsrpCreateApiPort, "create the api port \\Windows\\ApiPort"},
502 {TRUE, CsrpParseCommandLine, "parse the command line"},
503 {TRUE, CsrpInitVideo, "initialize video"},
504 {TRUE, CsrpApiRegisterDef, "initialize api definitions"},
505 {TRUE, CsrpCCTS, "connect client to server"},
506 {TRUE, CsrpInitWin32Csr, "load usermode dll"},
507 {TRUE, CsrpRunWinlogon, "run WinLogon"},
508 };
509
510 /**********************************************************************
511 * NAME
512 * CsrServerInitialization
513 *
514 * DESCRIPTION
515 * Initialize the Win32 environment subsystem server.
516 *
517 * RETURN VALUE
518 * TRUE: Initialization OK; otherwise FALSE.
519 */
520 BOOL STDCALL
521 CsrServerInitialization (
522 ULONG ArgumentCount,
523 PWSTR *ArgumentArray
524 )
525 {
526 INT i = 0;
527 NTSTATUS Status = STATUS_SUCCESS;
528
529 DPRINT("CSR: %s called\n", __FUNCTION__);
530
531 for (i=0; i < (sizeof InitRoutine / sizeof InitRoutine[0]); i++)
532 {
533 Status = InitRoutine[i].EntryPoint(ArgumentCount,ArgumentArray);
534 if(!NT_SUCCESS(Status))
535 {
536 DPRINT1("CSR: %s: failed to %s (Status=%08lx)\n",
537 __FUNCTION__,
538 InitRoutine[i].ErrorMessage,
539 Status);
540 if (InitRoutine[i].Required)
541 {
542 return FALSE;
543 }
544 }
545 }
546 if (CallInitComplete())
547 {
548 Status = SmCompleteSession (hSmApiPort,hSbApiPort,hApiPort);
549 return TRUE;
550 }
551 return FALSE;
552 }
553
554 /* EOF */