SM/CSR: move win32k.sys loading from the SM to the Win32 user mode server.
[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 extern PRTL_USER_PROCESS_PARAMETERS RtlProcessParameters;
38
39 static unsigned InitCompleteProcCount;
40 static CSRPLUGIN_INIT_COMPLETE_PROC *InitCompleteProcs = NULL;
41
42 HANDLE hSbApiPort = (HANDLE) 0;
43
44 HANDLE hBootstrapOk = (HANDLE) 0;
45
46 HANDLE hSmApiPort = (HANDLE) 0;
47
48 HANDLE hApiPort = (HANDLE) 0;
49
50 /**********************************************************************
51 * CsrpAddInitCompleteProc/1
52 */
53 static NTSTATUS FASTCALL
54 CsrpAddInitCompleteProc(CSRPLUGIN_INIT_COMPLETE_PROC Proc)
55 {
56 CSRPLUGIN_INIT_COMPLETE_PROC *NewProcs;
57
58 DPRINT("CSR: %s called\n", __FUNCTION__);
59
60 NewProcs = RtlAllocateHeap(CsrssApiHeap, 0,
61 (InitCompleteProcCount + 1)
62 * sizeof(CSRPLUGIN_INIT_COMPLETE_PROC));
63 if (NULL == NewProcs)
64 {
65 return STATUS_NO_MEMORY;
66 }
67 if (0 != InitCompleteProcCount)
68 {
69 RtlCopyMemory(NewProcs, InitCompleteProcs,
70 InitCompleteProcCount * sizeof(CSRPLUGIN_INIT_COMPLETE_PROC));
71 RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
72 }
73 NewProcs[InitCompleteProcCount] = Proc;
74 InitCompleteProcs = NewProcs;
75 InitCompleteProcCount++;
76
77 return STATUS_SUCCESS;
78 }
79
80 /**********************************************************************
81 * CallInitComplete/0
82 */
83 static BOOL FASTCALL
84 CallInitComplete(void)
85 {
86 BOOL Ok;
87 unsigned i;
88
89 DPRINT("CSR: %s called\n", __FUNCTION__);
90
91 Ok = TRUE;
92 if (0 != InitCompleteProcCount)
93 {
94 for (i = 0; i < InitCompleteProcCount && Ok; i++)
95 {
96 Ok = (*(InitCompleteProcs[i]))();
97 }
98 RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
99 }
100
101 return Ok;
102 }
103
104 ULONG
105 InitializeVideoAddressSpace(VOID);
106
107 /**********************************************************************
108 * CsrpParseCommandLine/2
109 */
110 static NTSTATUS
111 CsrpParseCommandLine (
112 ULONG ArgumentCount,
113 PWSTR *ArgumentArray
114 )
115 {
116 NTSTATUS Status;
117 OBJECT_ATTRIBUTES Attributes;
118
119 DPRINT("CSR: %s called\n", __FUNCTION__);
120
121
122 /* DbgPrint ("Arguments: %ld\n", ArgumentCount);
123 for (i = 0; i < ArgumentCount; i++)
124 {
125 DbgPrint ("Argument %ld: %S\n", i, ArgumentArray[i]);
126 }*/
127
128
129 /* create object directory ('\Windows') */
130 RtlCreateUnicodeString (&CsrDirectoryName,
131 L"\\Windows");
132
133 InitializeObjectAttributes (&Attributes,
134 &CsrDirectoryName,
135 OBJ_OPENIF,
136 NULL,
137 NULL);
138
139 Status = NtOpenDirectoryObject(&CsrObjectDirectory,
140 0xF000F, /* ea:??? */
141 &Attributes);
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 * CsrpCreateHeap/2
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/2
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 * CsrpLoadKernelModeDriver/2
406 */
407 static NTSTATUS
408 CsrpLoadKernelModeDriver (ULONG argc, PWSTR* argv)
409 {
410 NTSTATUS Status = STATUS_SUCCESS;
411 WCHAR Data [MAX_PATH + 1];
412 ULONG DataLength = sizeof Data;
413 ULONG DataType = 0;
414
415
416 DPRINT("SM: %s called\n", __FUNCTION__);
417
418 Status = SmLookupSubsystem (L"Kmode",
419 Data,
420 & DataLength,
421 & DataType,
422 RtlProcessParameters->Environment);
423 if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
424 {
425 WCHAR ImagePath [MAX_PATH + 1] = {0};
426 SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;
427
428 wcscpy (ImagePath, L"\\??\\");
429 wcscat (ImagePath, Data);
430 RtlZeroMemory (& ImageInfo, sizeof ImageInfo);
431 RtlInitUnicodeString (& ImageInfo.ModuleName, ImagePath);
432 Status = NtSetSystemInformation(SystemLoadAndCallImage,
433 & ImageInfo,
434 sizeof ImageInfo);
435 if(!NT_SUCCESS(Status))
436 {
437 DPRINT("WIN: %s: loading Kmode failed (Status=0x%08lx)\n",
438 __FUNCTION__, Status);
439 }
440 }
441 return Status;
442 }
443
444 /**********************************************************************
445 * CsrpCreateApiPort/2
446 */
447 static NTSTATUS
448 CsrpCreateApiPort (ULONG argc, PWSTR* argv)
449 {
450 DPRINT("CSR: %s called\n", __FUNCTION__);
451
452 return CsrpCreateListenPort (L"\\Windows\\ApiPort",
453 & hApiPort,
454 ServerApiPortThread);
455 }
456
457 /**********************************************************************
458 * CsrpApiRegisterDef/0
459 */
460 static NTSTATUS
461 CsrpApiRegisterDef (ULONG argc, PWSTR* argv)
462 {
463 return CsrApiRegisterDefinitions(NativeDefinitions);
464 }
465
466 /**********************************************************************
467 * CsrpCCTS/2
468 */
469 static NTSTATUS
470 CsrpCCTS (ULONG argc, PWSTR* argv)
471 {
472 return CsrClientConnectToServer();
473 }
474
475 /**********************************************************************
476 * CsrpRunWinlogon/0
477 *
478 * Start the logon process (winlogon.exe).
479 *
480 * TODO: this should be moved in CsrpCreateSession/x (one per session)
481 * TODO: in its own desktop (one logon desktop per winstation).
482 */
483 static NTSTATUS
484 CsrpRunWinlogon (ULONG argc, PWSTR* argv)
485 {
486 NTSTATUS Status = STATUS_SUCCESS;
487 UNICODE_STRING ImagePath;
488 UNICODE_STRING CommandLine;
489 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
490 RTL_PROCESS_INFO ProcessInfo;
491
492
493 DPRINT("CSR: %s called\n", __FUNCTION__);
494
495 /* initialize the process parameters */
496 RtlInitUnicodeString (& ImagePath, L"\\SystemRoot\\system32\\winlogon.exe");
497 RtlInitUnicodeString (& CommandLine, L"");
498 RtlCreateProcessParameters(& ProcessParameters,
499 & ImagePath,
500 NULL,
501 NULL,
502 & CommandLine,
503 NULL,
504 NULL,
505 NULL,
506 NULL,
507 NULL);
508 /* Create the winlogon process */
509 Status = RtlCreateUserProcess (& ImagePath,
510 OBJ_CASE_INSENSITIVE,
511 ProcessParameters,
512 NULL,
513 NULL,
514 NULL,
515 FALSE,
516 NULL,
517 NULL,
518 & ProcessInfo);
519 /* Cleanup */
520 RtlDestroyProcessParameters (ProcessParameters);
521 if (!NT_SUCCESS(Status))
522 {
523 DPRINT1("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
524 __FUNCTION__, Status);
525 }
526 ZwResumeThread(ProcessInfo.ThreadHandle, NULL);
527 return Status;
528 }
529
530
531
532 typedef NTSTATUS (* CSR_INIT_ROUTINE)(ULONG, PWSTR*);
533
534 struct {
535 BOOL Required;
536 CSR_INIT_ROUTINE EntryPoint;
537 PCHAR ErrorMessage;
538 } InitRoutine [] = {
539 {TRUE, CsrpCreateCallbackPort, "create the callback port \\Windows\\SbApiPort"},
540 {TRUE, CsrpRegisterSubsystem, "register with SM"},
541 {TRUE, CsrpCreateHeap, "create the CSR heap"},
542 {TRUE, CsrpCreateApiPort, "create the api port \\Windows\\ApiPort"},
543 {TRUE, CsrpParseCommandLine, "parse the command line"},
544 {TRUE, CsrpLoadKernelModeDriver, "load Kmode driver"},
545 {TRUE, CsrpInitVideo, "initialize video"},
546 {TRUE, CsrpApiRegisterDef, "initialize api definitions"},
547 {TRUE, CsrpCCTS, "connect client to server"},
548 {TRUE, CsrpInitWin32Csr, "load usermode dll"},
549 {TRUE, CsrpRunWinlogon, "run WinLogon"},
550 };
551
552 /**********************************************************************
553 * NAME
554 * CsrServerInitialization
555 *
556 * DESCRIPTION
557 * Initialize the Win32 environment subsystem server.
558 *
559 * RETURN VALUE
560 * TRUE: Initialization OK; otherwise FALSE.
561 */
562 BOOL STDCALL
563 CsrServerInitialization (
564 ULONG ArgumentCount,
565 PWSTR *ArgumentArray
566 )
567 {
568 INT i = 0;
569 NTSTATUS Status = STATUS_SUCCESS;
570
571 DPRINT("CSR: %s called\n", __FUNCTION__);
572
573 for (i=0; i < (sizeof InitRoutine / sizeof InitRoutine[0]); i++)
574 {
575 Status = InitRoutine[i].EntryPoint(ArgumentCount,ArgumentArray);
576 if(!NT_SUCCESS(Status))
577 {
578 DPRINT1("CSR: %s: failed to %s (Status=%08lx)\n",
579 __FUNCTION__,
580 InitRoutine[i].ErrorMessage,
581 Status);
582 if (InitRoutine[i].Required)
583 {
584 return FALSE;
585 }
586 }
587 }
588 if (CallInitComplete())
589 {
590 Status = SmCompleteSession (hSmApiPort,hSbApiPort,hApiPort);
591 return TRUE;
592 }
593 return FALSE;
594 }
595
596 /* EOF */