Add new header for native user-mode functios inside the NT library inside the NDK...
[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 <windows.h>
14 #define NTOS_MODE_USER
15 #include <ndk/ntndk.h>
16 #include <ntdll/csr.h>
17 #include <ntdll/ldr.h>
18 #include <rosrtl/string.h>
19 #include <sm/helper.h>
20
21 #include "api.h"
22 #include "csrplugin.h"
23
24 #define NDEBUG
25 #include <debug.h>
26
27 /* GLOBALS ******************************************************************/
28
29 HANDLE CsrHeap = (HANDLE) 0;
30
31 HANDLE CsrObjectDirectory = (HANDLE) 0;
32
33 UNICODE_STRING CsrDirectoryName;
34
35 extern HANDLE CsrssApiHeap;
36 extern PRTL_USER_PROCESS_PARAMETERS RtlProcessParameters;
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 OBJ_OPENIF,
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 * CsrpCreateHeap/2
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/2
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 * CsrpLoadKernelModeDriver/2
405 */
406 static NTSTATUS
407 CsrpLoadKernelModeDriver (ULONG argc, PWSTR* argv)
408 {
409 NTSTATUS Status = STATUS_SUCCESS;
410 WCHAR Data [MAX_PATH + 1];
411 ULONG DataLength = sizeof Data;
412 ULONG DataType = 0;
413
414
415 DPRINT("SM: %s called\n", __FUNCTION__);
416
417 Status = SmLookupSubsystem (L"Kmode",
418 Data,
419 & DataLength,
420 & DataType,
421 RtlProcessParameters->Environment);
422 if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
423 {
424 WCHAR ImagePath [MAX_PATH + 1] = {0};
425 UNICODE_STRING ModuleName;
426
427 wcscpy (ImagePath, L"\\??\\");
428 wcscat (ImagePath, Data);
429 RtlInitUnicodeString (& ModuleName, ImagePath);
430 Status = NtSetSystemInformation(/* FIXME: SystemLoadAndCallImage */
431 SystemExtendServiceTableInformation,
432 & ModuleName,
433 sizeof ModuleName);
434 if(!NT_SUCCESS(Status))
435 {
436 DPRINT("WIN: %s: loading Kmode failed (Status=0x%08lx)\n",
437 __FUNCTION__, Status);
438 }
439 }
440 return Status;
441 }
442
443 /**********************************************************************
444 * CsrpCreateApiPort/2
445 */
446 static NTSTATUS
447 CsrpCreateApiPort (ULONG argc, PWSTR* argv)
448 {
449 DPRINT("CSR: %s called\n", __FUNCTION__);
450
451 return CsrpCreateListenPort (L"\\Windows\\ApiPort",
452 & hApiPort,
453 ServerApiPortThread);
454 }
455
456 /**********************************************************************
457 * CsrpApiRegisterDef/0
458 */
459 static NTSTATUS
460 CsrpApiRegisterDef (ULONG argc, PWSTR* argv)
461 {
462 return CsrApiRegisterDefinitions(NativeDefinitions);
463 }
464
465 /**********************************************************************
466 * CsrpCCTS/2
467 */
468 static NTSTATUS
469 CsrpCCTS (ULONG argc, PWSTR* argv)
470 {
471 return CsrClientConnectToServer();
472 }
473
474 /**********************************************************************
475 * CsrpRunWinlogon/0
476 *
477 * Start the logon process (winlogon.exe).
478 *
479 * TODO: this should be moved in CsrpCreateSession/x (one per session)
480 * TODO: in its own desktop (one logon desktop per winstation).
481 */
482 static NTSTATUS
483 CsrpRunWinlogon (ULONG argc, PWSTR* argv)
484 {
485 NTSTATUS Status = STATUS_SUCCESS;
486 UNICODE_STRING ImagePath;
487 UNICODE_STRING CommandLine;
488 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
489 RTL_PROCESS_INFO ProcessInfo;
490
491
492 DPRINT("CSR: %s called\n", __FUNCTION__);
493
494 /* initialize the process parameters */
495 RtlInitUnicodeString (& ImagePath, L"\\SystemRoot\\system32\\winlogon.exe");
496 RtlInitUnicodeString (& CommandLine, L"");
497 RtlCreateProcessParameters(& ProcessParameters,
498 & ImagePath,
499 NULL,
500 NULL,
501 & CommandLine,
502 NULL,
503 NULL,
504 NULL,
505 NULL,
506 NULL);
507 /* Create the winlogon process */
508 Status = RtlCreateUserProcess (& ImagePath,
509 OBJ_CASE_INSENSITIVE,
510 ProcessParameters,
511 NULL,
512 NULL,
513 NULL,
514 FALSE,
515 NULL,
516 NULL,
517 & ProcessInfo);
518 /* Cleanup */
519 RtlDestroyProcessParameters (ProcessParameters);
520 if (!NT_SUCCESS(Status))
521 {
522 DPRINT1("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
523 __FUNCTION__, Status);
524 }
525 ZwResumeThread(ProcessInfo.ThreadHandle, NULL);
526 return Status;
527 }
528
529
530
531 typedef NTSTATUS (* CSR_INIT_ROUTINE)(ULONG, PWSTR*);
532
533 struct {
534 BOOL Required;
535 CSR_INIT_ROUTINE EntryPoint;
536 PCHAR ErrorMessage;
537 } InitRoutine [] = {
538 {TRUE, CsrpCreateCallbackPort, "create the callback port \\Windows\\SbApiPort"},
539 {TRUE, CsrpRegisterSubsystem, "register with SM"},
540 {TRUE, CsrpCreateHeap, "create the CSR heap"},
541 {TRUE, CsrpCreateApiPort, "create the api port \\Windows\\ApiPort"},
542 {TRUE, CsrpParseCommandLine, "parse the command line"},
543 {TRUE, CsrpLoadKernelModeDriver, "load Kmode driver"},
544 {TRUE, CsrpInitVideo, "initialize video"},
545 {TRUE, CsrpApiRegisterDef, "initialize api definitions"},
546 {TRUE, CsrpCCTS, "connect client to server"},
547 {TRUE, CsrpInitWin32Csr, "load usermode dll"},
548 {TRUE, CsrpRunWinlogon, "run WinLogon"},
549 };
550
551 /**********************************************************************
552 * NAME
553 * CsrServerInitialization
554 *
555 * DESCRIPTION
556 * Initialize the Win32 environment subsystem server.
557 *
558 * RETURN VALUE
559 * TRUE: Initialization OK; otherwise FALSE.
560 */
561 BOOL STDCALL
562 CsrServerInitialization (
563 ULONG ArgumentCount,
564 PWSTR *ArgumentArray
565 )
566 {
567 INT i = 0;
568 NTSTATUS Status = STATUS_SUCCESS;
569
570 DPRINT("CSR: %s called\n", __FUNCTION__);
571
572 for (i=0; i < (sizeof InitRoutine / sizeof InitRoutine[0]); i++)
573 {
574 Status = InitRoutine[i].EntryPoint(ArgumentCount,ArgumentArray);
575 if(!NT_SUCCESS(Status))
576 {
577 DPRINT1("CSR: %s: failed to %s (Status=%08lx)\n",
578 __FUNCTION__,
579 InitRoutine[i].ErrorMessage,
580 Status);
581 if (InitRoutine[i].Required)
582 {
583 return FALSE;
584 }
585 }
586 }
587 if (CallInitComplete())
588 {
589 Status = SmCompleteSession (hSmApiPort,hSbApiPort,hApiPort);
590 return TRUE;
591 }
592 return FALSE;
593 }
594
595 /* EOF */