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