Files forgotten in r19815
[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 Exports.CsrEnumProcessesProc = CsrEnumProcesses;
204 if (! (*InitProc)(&ApiDefinitions, &ObjectDefinitions, &InitCompleteProc,
205 &Exports, CsrssApiHeap))
206 {
207 return STATUS_UNSUCCESSFUL;
208 }
209
210 Status = CsrApiRegisterDefinitions(ApiDefinitions);
211 if (! NT_SUCCESS(Status))
212 {
213 return Status;
214 }
215 Status = CsrRegisterObjectDefinitions(ObjectDefinitions);
216 if (! NT_SUCCESS(Status))
217 {
218 return Status;
219 }
220 if (NULL != InitCompleteProc)
221 {
222 Status = CsrpAddInitCompleteProc(InitCompleteProc);
223 }
224
225 return Status;
226 }
227
228 CSRSS_API_DEFINITION NativeDefinitions[] =
229 {
230 CSRSS_DEFINE_API(CREATE_PROCESS, CsrCreateProcess),
231 CSRSS_DEFINE_API(TERMINATE_PROCESS, CsrTerminateProcess),
232 CSRSS_DEFINE_API(CONNECT_PROCESS, CsrConnectProcess),
233 CSRSS_DEFINE_API(REGISTER_SERVICES_PROCESS, CsrRegisterServicesProcess),
234 CSRSS_DEFINE_API(GET_SHUTDOWN_PARAMETERS, CsrGetShutdownParameters),
235 CSRSS_DEFINE_API(SET_SHUTDOWN_PARAMETERS, CsrSetShutdownParameters),
236 CSRSS_DEFINE_API(GET_INPUT_HANDLE, CsrGetInputHandle),
237 CSRSS_DEFINE_API(GET_OUTPUT_HANDLE, CsrGetOutputHandle),
238 CSRSS_DEFINE_API(CLOSE_HANDLE, CsrCloseHandle),
239 CSRSS_DEFINE_API(VERIFY_HANDLE, CsrVerifyHandle),
240 CSRSS_DEFINE_API(DUPLICATE_HANDLE, CsrDuplicateHandle),
241 CSRSS_DEFINE_API(GET_INPUT_WAIT_HANDLE, CsrGetInputWaitHandle),
242 { 0, 0, NULL }
243 };
244
245 static NTSTATUS STDCALL
246 CsrpCreateListenPort (IN LPWSTR Name,
247 IN OUT PHANDLE Port,
248 IN PTHREAD_START_ROUTINE ListenThread)
249 {
250 NTSTATUS Status = STATUS_SUCCESS;
251 OBJECT_ATTRIBUTES PortAttributes;
252 UNICODE_STRING PortName;
253
254 DPRINT("CSR: %s called\n", __FUNCTION__);
255
256 RtlInitUnicodeString (& PortName, Name);
257 InitializeObjectAttributes (& PortAttributes,
258 & PortName,
259 0,
260 NULL,
261 NULL);
262 Status = NtCreatePort ( Port,
263 & PortAttributes,
264 LPC_MAX_DATA_LENGTH, /* TODO: make caller set it*/
265 LPC_MAX_MESSAGE_LENGTH, /* TODO: make caller set it*/
266 0); /* TODO: make caller set it*/
267 if(!NT_SUCCESS(Status))
268 {
269 DPRINT1("CSR: %s: NtCreatePort failed (Status=%08lx)\n",
270 __FUNCTION__, Status);
271 return Status;
272 }
273 Status = RtlCreateUserThread(NtCurrentProcess(),
274 NULL,
275 FALSE,
276 0,
277 0,
278 0,
279 (PTHREAD_START_ROUTINE) ListenThread,
280 Port,
281 NULL,
282 NULL);
283 return Status;
284 }
285
286 /* === INIT ROUTINES === */
287
288 /**********************************************************************
289 * CsrpCreateHeap/3
290 */
291 static NTSTATUS
292 CsrpCreateHeap (int argc, char ** argv, char ** envp)
293 {
294 DPRINT("CSR: %s called\n", __FUNCTION__);
295
296 CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE,
297 NULL,
298 65536,
299 65536,
300 NULL,
301 NULL);
302 if (CsrssApiHeap == NULL)
303 {
304 return STATUS_UNSUCCESSFUL;
305 }
306 return STATUS_SUCCESS;
307 }
308
309 /**********************************************************************
310 * CsrpCreateCallbackPort/3
311 */
312 static NTSTATUS
313 CsrpCreateCallbackPort (int argc, char ** argv, char ** envp)
314 {
315 DPRINT("CSR: %s called\n", __FUNCTION__);
316
317 return CsrpCreateListenPort (L"\\Windows\\SbApiPort",
318 & hSbApiPort,
319 ServerSbApiPortThread);
320 }
321
322 /**********************************************************************
323 * CsrpRegisterSubsystem/3
324 */
325 static NTSTATUS
326 CsrpRegisterSubsystem (int argc, char ** argv, char ** envp)
327 {
328 NTSTATUS Status = STATUS_SUCCESS;
329 OBJECT_ATTRIBUTES BootstrapOkAttributes;
330 UNICODE_STRING Name;
331
332 DPRINT("CSR: %s called\n", __FUNCTION__);
333
334 /*
335 * Create the event object the callback port
336 * thread will signal *if* the SM will
337 * authorize us to bootstrap.
338 */
339 RtlInitUnicodeString (& Name, L"\\CsrssBooting");
340 InitializeObjectAttributes(& BootstrapOkAttributes,
341 & Name,
342 0, NULL, NULL);
343 Status = NtCreateEvent (& hBootstrapOk,
344 EVENT_ALL_ACCESS,
345 & BootstrapOkAttributes,
346 SynchronizationEvent,
347 FALSE);
348 if(!NT_SUCCESS(Status))
349 {
350 DPRINT("CSR: %s: NtCreateEvent failed (Status=0x%08lx)\n",
351 __FUNCTION__, Status);
352 return Status;
353 }
354 /*
355 * Let's tell the SM a new environment
356 * subsystem server is in the system.
357 */
358 RtlInitUnicodeString (& Name, L"\\Windows\\SbApiPort");
359 DPRINT("CSR: %s: registering with SM for\n IMAGE_SUBSYSTEM_WINDOWS_CUI == 3\n", __FUNCTION__);
360 Status = SmConnectApiPort (& Name,
361 hSbApiPort,
362 IMAGE_SUBSYSTEM_WINDOWS_CUI,
363 & hSmApiPort);
364 if(!NT_SUCCESS(Status))
365 {
366 DPRINT("CSR: %s unable to connect to the SM (Status=0x%08lx)\n",
367 __FUNCTION__, Status);
368 NtClose (hBootstrapOk);
369 return Status;
370 }
371 /*
372 * Wait for SM to reply OK... If the SM
373 * won't answer, we hang here forever!
374 */
375 DPRINT("CSR: %s: waiting for SM to OK boot...\n", __FUNCTION__);
376 Status = NtWaitForSingleObject (hBootstrapOk,
377 FALSE,
378 NULL);
379 NtClose (hBootstrapOk);
380 return Status;
381 }
382
383 /**********************************************************************
384 * EnvpToUnicodeString/2
385 */
386 static ULONG FASTCALL
387 EnvpToUnicodeString (char ** envp, PUNICODE_STRING UnicodeEnv)
388 {
389 ULONG CharCount = 0;
390 ULONG Index = 0;
391 ANSI_STRING AnsiEnv;
392
393 UnicodeEnv->Buffer = NULL;
394
395 for (Index=0; NULL != envp[Index]; Index++)
396 {
397 CharCount += strlen (envp[Index]);
398 ++ CharCount;
399 }
400 ++ CharCount;
401
402 AnsiEnv.Buffer = RtlAllocateHeap (RtlGetProcessHeap(), 0, CharCount);
403 if (NULL != AnsiEnv.Buffer)
404 {
405
406 PCHAR WritePos = AnsiEnv.Buffer;
407
408 for (Index=0; NULL != envp[Index]; Index++)
409 {
410 strcpy (WritePos, envp[Index]);
411 WritePos += strlen (envp[Index]) + 1;
412 }
413
414 /* FIXME: the last (double) nullterm should perhaps not be included in Length
415 * but only in MaximumLength. -Gunnar */
416 AnsiEnv.Buffer [CharCount-1] = '\0';
417 AnsiEnv.Length = CharCount;
418 AnsiEnv.MaximumLength = CharCount;
419
420 RtlAnsiStringToUnicodeString (UnicodeEnv, & AnsiEnv, TRUE);
421 RtlFreeHeap (RtlGetProcessHeap(), 0, AnsiEnv.Buffer);
422 }
423 return CharCount;
424 }
425 /**********************************************************************
426 * CsrpLoadKernelModeDriver/3
427 */
428 static NTSTATUS
429 CsrpLoadKernelModeDriver (int argc, char ** argv, char ** envp)
430 {
431 NTSTATUS Status = STATUS_SUCCESS;
432 WCHAR Data [MAX_PATH + 1];
433 ULONG DataLength = sizeof Data;
434 ULONG DataType = 0;
435 UNICODE_STRING Environment;
436
437
438 DPRINT("SM: %s called\n", __FUNCTION__);
439
440
441 EnvpToUnicodeString (envp, & Environment);
442 Status = SmLookupSubsystem (L"Kmode",
443 Data,
444 & DataLength,
445 & DataType,
446 Environment.Buffer);
447 RtlFreeUnicodeString (& Environment);
448 if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
449 {
450 WCHAR ImagePath [MAX_PATH + 1] = {0};
451 UNICODE_STRING ModuleName;
452
453 wcscpy (ImagePath, L"\\??\\");
454 wcscat (ImagePath, Data);
455 RtlInitUnicodeString (& ModuleName, ImagePath);
456 Status = NtSetSystemInformation(/* FIXME: SystemLoadAndCallImage */
457 SystemExtendServiceTableInformation,
458 & ModuleName,
459 sizeof ModuleName);
460 if(!NT_SUCCESS(Status))
461 {
462 DPRINT("WIN: %s: loading Kmode failed (Status=0x%08lx)\n",
463 __FUNCTION__, Status);
464 }
465 }
466 return Status;
467 }
468
469 /**********************************************************************
470 * CsrpCreateApiPort/2
471 */
472 static NTSTATUS
473 CsrpCreateApiPort (int argc, char ** argv, char ** envp)
474 {
475 DPRINT("CSR: %s called\n", __FUNCTION__);
476
477 return CsrpCreateListenPort (L"\\Windows\\ApiPort",
478 & hApiPort,
479 ServerApiPortThread);
480 }
481
482 /**********************************************************************
483 * CsrpApiRegisterDef/0
484 */
485 static NTSTATUS
486 CsrpApiRegisterDef (int argc, char ** argv, char ** envp)
487 {
488 return CsrApiRegisterDefinitions(NativeDefinitions);
489 }
490
491 /**********************************************************************
492 * CsrpCCTS/2
493 */
494 static NTSTATUS
495 CsrpCCTS (int argc, char ** argv, char ** envp)
496 {
497 ULONG Dummy;
498 ULONG DummyLength = sizeof(Dummy);
499 return CsrClientConnectToServer(L"\\Windows",
500 0, &Dummy, &DummyLength, NULL);
501 }
502
503 /**********************************************************************
504 * CsrpRunWinlogon/0
505 *
506 * Start the logon process (winlogon.exe).
507 *
508 * TODO: this should be moved in CsrpCreateSession/x (one per session)
509 * TODO: in its own desktop (one logon desktop per winstation).
510 */
511 static NTSTATUS
512 CsrpRunWinlogon (int argc, char ** argv, char ** envp)
513 {
514 NTSTATUS Status = STATUS_SUCCESS;
515 UNICODE_STRING ImagePath;
516 UNICODE_STRING CommandLine;
517 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
518 RTL_USER_PROCESS_INFORMATION ProcessInfo;
519
520
521 DPRINT("CSR: %s called\n", __FUNCTION__);
522
523 /* initialize the process parameters */
524 RtlInitUnicodeString (& ImagePath, L"\\SystemRoot\\system32\\winlogon.exe");
525 RtlInitUnicodeString (& CommandLine, L"");
526 RtlCreateProcessParameters(& ProcessParameters,
527 & ImagePath,
528 NULL,
529 NULL,
530 & CommandLine,
531 NULL,
532 NULL,
533 NULL,
534 NULL,
535 NULL);
536 /* Create the winlogon process */
537 Status = RtlCreateUserProcess (& ImagePath,
538 OBJ_CASE_INSENSITIVE,
539 ProcessParameters,
540 NULL,
541 NULL,
542 NULL,
543 FALSE,
544 NULL,
545 NULL,
546 & ProcessInfo);
547 /* Cleanup */
548 RtlDestroyProcessParameters (ProcessParameters);
549 if (!NT_SUCCESS(Status))
550 {
551 DPRINT1("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
552 __FUNCTION__, Status);
553 }
554 ZwResumeThread(ProcessInfo.ThreadHandle, NULL);
555 return Status;
556 }
557
558
559
560 typedef NTSTATUS (* CSR_INIT_ROUTINE)(int,char**,char**);
561
562 struct {
563 BOOL Required;
564 CSR_INIT_ROUTINE EntryPoint;
565 PCHAR ErrorMessage;
566 } InitRoutine [] = {
567 {TRUE, CsrpCreateCallbackPort, "create the callback port \\Windows\\SbApiPort"},
568 {TRUE, CsrpRegisterSubsystem, "register with SM"},
569 {TRUE, CsrpCreateHeap, "create the CSR heap"},
570 {TRUE, CsrpCreateApiPort, "create the api port \\Windows\\ApiPort"},
571 {TRUE, CsrpCreateObjectDirectory,"create the object directory \\Windows"},
572 {TRUE, CsrpLoadKernelModeDriver, "load Kmode driver"},
573 {TRUE, CsrpInitVideo, "initialize video"},
574 {TRUE, CsrpApiRegisterDef, "initialize api definitions"},
575 {TRUE, CsrpCCTS, "connect client to server"},
576 {TRUE, CsrpInitWin32Csr, "load usermode dll"},
577 {TRUE, CsrpRunWinlogon, "run WinLogon"},
578 };
579
580 /**********************************************************************
581 * NAME
582 * CsrServerInitialization
583 *
584 * DESCRIPTION
585 * Initialize the Win32 environment subsystem server.
586 *
587 * RETURN VALUE
588 * TRUE: Initialization OK; otherwise FALSE.
589 */
590 BOOL STDCALL
591 CsrServerInitialization (
592 int argc,
593 char ** argv,
594 char ** envp
595 )
596 {
597 UINT i = 0;
598 NTSTATUS Status = STATUS_SUCCESS;
599
600 DPRINT("CSR: %s called\n", __FUNCTION__);
601
602 for (i=0; i < (sizeof InitRoutine / sizeof InitRoutine[0]); i++)
603 {
604 Status = InitRoutine[i].EntryPoint(argc,argv,envp);
605 if(!NT_SUCCESS(Status))
606 {
607 DPRINT1("CSR: %s: failed to %s (Status=%08lx)\n",
608 __FUNCTION__,
609 InitRoutine[i].ErrorMessage,
610 Status);
611 if (InitRoutine[i].Required)
612 {
613 return FALSE;
614 }
615 }
616 }
617 if (CallInitComplete())
618 {
619 Status = SmCompleteSession (hSmApiPort,hSbApiPort,hApiPort);
620 return TRUE;
621 }
622 return FALSE;
623 }
624
625 /* EOF */