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