5947c717726c75b278ed616b421296903c286c4f
[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 = NtOpenDirectoryObject(&CsrObjectDirectory,
139 0xF000F, /* ea:??? */
140 &Attributes);
141 return Status;
142 }
143
144 /**********************************************************************
145 * CsrpInitVideo/0
146 *
147 * TODO: we need a virtual device for sessions other than
148 * TODO: the console one
149 */
150 static NTSTATUS
151 CsrpInitVideo (ULONG argc, PWSTR* argv)
152 {
153 OBJECT_ATTRIBUTES ObjectAttributes;
154 UNICODE_STRING DeviceName;
155 IO_STATUS_BLOCK Iosb;
156 HANDLE VideoHandle = (HANDLE) 0;
157 NTSTATUS Status = STATUS_SUCCESS;
158
159 DPRINT("CSR: %s called\n", __FUNCTION__);
160
161 InitializeVideoAddressSpace();
162
163 RtlRosInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\DISPLAY1");
164 InitializeObjectAttributes(&ObjectAttributes,
165 &DeviceName,
166 0,
167 NULL,
168 NULL);
169 Status = NtOpenFile(&VideoHandle,
170 FILE_ALL_ACCESS,
171 &ObjectAttributes,
172 &Iosb,
173 0,
174 0);
175 if (NT_SUCCESS(Status))
176 {
177 NtClose(VideoHandle);
178 }
179 return Status;
180 }
181
182 /**********************************************************************
183 * CsrpInitWin32Csr/0
184 *
185 * TODO: this function should be turned more general to load an
186 * TODO: hosted server DLL as received from the command line;
187 * TODO: for instance: ServerDll=winsrv:ConServerDllInitialization,2
188 * TODO: ^method ^dll ^api ^sid
189 * TODO:
190 * TODO: CsrpHostServerDll (LPWSTR DllName,
191 * TODO: LPWSTR ApiName,
192 * TODO: DWORD ServerId)
193 */
194 static NTSTATUS
195 CsrpInitWin32Csr (ULONG argc, PWSTR* argv)
196 {
197 NTSTATUS Status;
198 UNICODE_STRING DllName;
199 HINSTANCE hInst;
200 ANSI_STRING ProcName;
201 CSRPLUGIN_INITIALIZE_PROC InitProc;
202 CSRSS_EXPORTED_FUNCS Exports;
203 PCSRSS_API_DEFINITION ApiDefinitions;
204 PCSRSS_OBJECT_DEFINITION ObjectDefinitions;
205 CSRPLUGIN_INIT_COMPLETE_PROC InitCompleteProc;
206
207 DPRINT("CSR: %s called\n", __FUNCTION__);
208
209 RtlInitUnicodeString(&DllName, L"win32csr.dll");
210 Status = LdrLoadDll(NULL, 0, &DllName, (PVOID *) &hInst);
211 if (! NT_SUCCESS(Status))
212 {
213 return Status;
214 }
215 RtlInitAnsiString(&ProcName, "Win32CsrInitialization");
216 Status = LdrGetProcedureAddress(hInst, &ProcName, 0, (PVOID *) &InitProc);
217 if (! NT_SUCCESS(Status))
218 {
219 return Status;
220 }
221 Exports.CsrInsertObjectProc = CsrInsertObject;
222 Exports.CsrGetObjectProc = CsrGetObject;
223 Exports.CsrReleaseObjectProc = CsrReleaseObject;
224 if (! (*InitProc)(&ApiDefinitions, &ObjectDefinitions, &InitCompleteProc,
225 &Exports, CsrssApiHeap))
226 {
227 return STATUS_UNSUCCESSFUL;
228 }
229
230 Status = CsrApiRegisterDefinitions(ApiDefinitions);
231 if (! NT_SUCCESS(Status))
232 {
233 return Status;
234 }
235 Status = CsrRegisterObjectDefinitions(ObjectDefinitions);
236 if (! NT_SUCCESS(Status))
237 {
238 return Status;
239 }
240 if (NULL != InitCompleteProc)
241 {
242 Status = CsrpAddInitCompleteProc(InitCompleteProc);
243 }
244
245 return Status;
246 }
247
248 CSRSS_API_DEFINITION NativeDefinitions[] =
249 {
250 CSRSS_DEFINE_API(CSRSS_CREATE_PROCESS, CsrCreateProcess),
251 CSRSS_DEFINE_API(CSRSS_TERMINATE_PROCESS, CsrTerminateProcess),
252 CSRSS_DEFINE_API(CSRSS_CONNECT_PROCESS, CsrConnectProcess),
253 CSRSS_DEFINE_API(CSRSS_REGISTER_SERVICES_PROCESS, CsrRegisterServicesProcess),
254 CSRSS_DEFINE_API(CSRSS_GET_SHUTDOWN_PARAMETERS, CsrGetShutdownParameters),
255 CSRSS_DEFINE_API(CSRSS_SET_SHUTDOWN_PARAMETERS, CsrSetShutdownParameters),
256 CSRSS_DEFINE_API(CSRSS_GET_INPUT_HANDLE, CsrGetInputHandle),
257 CSRSS_DEFINE_API(CSRSS_GET_OUTPUT_HANDLE, CsrGetOutputHandle),
258 CSRSS_DEFINE_API(CSRSS_CLOSE_HANDLE, CsrCloseHandle),
259 CSRSS_DEFINE_API(CSRSS_VERIFY_HANDLE, CsrVerifyHandle),
260 CSRSS_DEFINE_API(CSRSS_DUPLICATE_HANDLE, CsrDuplicateHandle),
261 CSRSS_DEFINE_API(CSRSS_GET_INPUT_WAIT_HANDLE, CsrGetInputWaitHandle),
262 { 0, 0, 0, NULL }
263 };
264
265 static NTSTATUS STDCALL
266 CsrpCreateListenPort (IN LPWSTR Name,
267 IN OUT PHANDLE Port,
268 IN PTHREAD_START_ROUTINE ListenThread)
269 {
270 NTSTATUS Status = STATUS_SUCCESS;
271 OBJECT_ATTRIBUTES PortAttributes;
272 UNICODE_STRING PortName;
273
274 DPRINT("CSR: %s called\n", __FUNCTION__);
275
276 RtlInitUnicodeString (& PortName, Name);
277 InitializeObjectAttributes (& PortAttributes,
278 & PortName,
279 0,
280 NULL,
281 NULL);
282 Status = NtCreatePort ( Port,
283 & PortAttributes,
284 260, /* TODO: make caller set it*/
285 328, /* TODO: make caller set it*/
286 0); /* TODO: make caller set it*/
287 if(!NT_SUCCESS(Status))
288 {
289 DPRINT1("CSR: %s: NtCreatePort failed (Status=%08lx)\n",
290 __FUNCTION__, Status);
291 return Status;
292 }
293 Status = RtlCreateUserThread(NtCurrentProcess(),
294 NULL,
295 FALSE,
296 0,
297 NULL,
298 NULL,
299 (PTHREAD_START_ROUTINE) ListenThread,
300 Port,
301 NULL,
302 NULL);
303 return Status;
304 }
305
306 /* === INIT ROUTINES === */
307
308 /**********************************************************************
309 * CsrpCreateCallbackPort/0
310 */
311 static NTSTATUS
312 CsrpCreateHeap (ULONG argc, PWSTR* argv)
313 {
314 DPRINT("CSR: %s called\n", __FUNCTION__);
315
316 CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE,
317 NULL,
318 65536,
319 65536,
320 NULL,
321 NULL);
322 if (CsrssApiHeap == NULL)
323 {
324 return STATUS_UNSUCCESSFUL;
325 }
326 return STATUS_SUCCESS;
327 }
328
329 /**********************************************************************
330 * CsrpCreateCallbackPort/0
331 */
332 static NTSTATUS
333 CsrpCreateCallbackPort (ULONG argc, PWSTR* argv)
334 {
335 DPRINT("CSR: %s called\n", __FUNCTION__);
336
337 return CsrpCreateListenPort (L"\\Windows\\SbApiPort",
338 & hSbApiPort,
339 ServerSbApiPortThread);
340 }
341
342 /**********************************************************************
343 * CsrpRegisterSubsystem/2
344 */
345 static NTSTATUS
346 CsrpRegisterSubsystem (ULONG argc, PWSTR* argv)
347 {
348 NTSTATUS Status = STATUS_SUCCESS;
349 OBJECT_ATTRIBUTES BootstrapOkAttributes;
350 UNICODE_STRING Name;
351
352 DPRINT("CSR: %s called\n", __FUNCTION__);
353
354 /*
355 * Create the event object the callback port
356 * thread will signal *if* the SM will
357 * authorize us to bootstrap.
358 */
359 RtlInitUnicodeString (& Name, L"\\CsrssBooting");
360 InitializeObjectAttributes(& BootstrapOkAttributes,
361 & Name,
362 0, NULL, NULL);
363 Status = NtCreateEvent (& hBootstrapOk,
364 EVENT_ALL_ACCESS,
365 & BootstrapOkAttributes,
366 SynchronizationEvent,
367 FALSE);
368 if(!NT_SUCCESS(Status))
369 {
370 DPRINT("CSR: %s: NtCreateEvent failed (Status=0x%08lx)\n",
371 __FUNCTION__, Status);
372 return Status;
373 }
374 /*
375 * Let's tell the SM a new environment
376 * subsystem server is in the system.
377 */
378 RtlInitUnicodeString (& Name, L"\\Windows\\SbApiPort");
379 DPRINT("CSR: %s: registering with SM for\n IMAGE_SUBSYSTEM_WINDOWS_CUI == 3\n", __FUNCTION__);
380 Status = SmConnectApiPort (& Name,
381 hSbApiPort,
382 IMAGE_SUBSYSTEM_WINDOWS_CUI,
383 & hSmApiPort);
384 if(!NT_SUCCESS(Status))
385 {
386 DPRINT("CSR: %s unable to connect to the SM (Status=0x%08lx)\n",
387 __FUNCTION__, Status);
388 NtClose (hBootstrapOk);
389 return Status;
390 }
391 /*
392 * Wait for SM to reply OK... If the SM
393 * won't answer, we hang here forever!
394 */
395 DPRINT("CSR: %s: waiting for SM to OK boot...\n", __FUNCTION__);
396 Status = NtWaitForSingleObject (hBootstrapOk,
397 FALSE,
398 NULL);
399 NtClose (hBootstrapOk);
400 return Status;
401 }
402
403 /**********************************************************************
404 * CsrpCreateApiPort/0
405 */
406 static NTSTATUS
407 CsrpCreateApiPort (ULONG argc, PWSTR* argv)
408 {
409 DPRINT("CSR: %s called\n", __FUNCTION__);
410
411 return CsrpCreateListenPort (L"\\Windows\\ApiPort",
412 & hApiPort,
413 ServerApiPortThread);
414 }
415
416 /**********************************************************************
417 * CsrpApiRegisterDef/0
418 */
419 static NTSTATUS
420 CsrpApiRegisterDef (ULONG argc, PWSTR* argv)
421 {
422 return CsrApiRegisterDefinitions(NativeDefinitions);
423 }
424
425 /**********************************************************************
426 * CsrpCCTS/2
427 */
428 static NTSTATUS
429 CsrpCCTS (ULONG argc, PWSTR* argv)
430 {
431 return CsrClientConnectToServer();
432 }
433
434 /**********************************************************************
435 * CsrpRunWinlogon/0
436 *
437 * Start the logon process (winlogon.exe).
438 *
439 * TODO: this should be moved in CsrpCreateSession/x (one per session)
440 * TODO: in its own desktop (one logon desktop per winstation).
441 */
442 static NTSTATUS
443 CsrpRunWinlogon (ULONG argc, PWSTR* argv)
444 {
445 NTSTATUS Status = STATUS_SUCCESS;
446 UNICODE_STRING ImagePath;
447 UNICODE_STRING CommandLine;
448 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
449 RTL_PROCESS_INFO ProcessInfo;
450
451
452 DPRINT("CSR: %s called\n", __FUNCTION__);
453
454 /* initialize the process parameters */
455 RtlInitUnicodeString (& ImagePath, L"\\SystemRoot\\system32\\winlogon.exe");
456 RtlInitUnicodeString (& CommandLine, L"");
457 RtlCreateProcessParameters(& ProcessParameters,
458 & ImagePath,
459 NULL,
460 NULL,
461 & CommandLine,
462 NULL,
463 NULL,
464 NULL,
465 NULL,
466 NULL);
467 /* Create the winlogon process */
468 Status = RtlCreateUserProcess (& ImagePath,
469 OBJ_CASE_INSENSITIVE,
470 ProcessParameters,
471 NULL,
472 NULL,
473 NULL,
474 FALSE,
475 NULL,
476 NULL,
477 & ProcessInfo);
478 /* Cleanup */
479 RtlDestroyProcessParameters (ProcessParameters);
480 if (!NT_SUCCESS(Status))
481 {
482 DPRINT1("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
483 __FUNCTION__, Status);
484 }
485 ZwResumeThread(ProcessInfo.ThreadHandle, NULL);
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 */