3 * reactos/subsys/csrss/init.c
5 * Initialize the CSRSS subsystem server process.
7 * ReactOS Operating System
11 /* INCLUDES ******************************************************************/
18 /* GLOBALS ******************************************************************/
20 HANDLE CsrHeap
= (HANDLE
) 0;
22 HANDLE CsrObjectDirectory
= (HANDLE
) 0;
24 UNICODE_STRING CsrDirectoryName
;
26 extern HANDLE CsrssApiHeap
;
28 static unsigned InitCompleteProcCount
;
29 static CSRPLUGIN_INIT_COMPLETE_PROC
*InitCompleteProcs
= NULL
;
31 static unsigned HardErrorProcCount
;
32 static CSRPLUGIN_HARDERROR_PROC
*HardErrorProcs
= NULL
;
34 HANDLE hSbApiPort
= (HANDLE
) 0;
36 HANDLE hBootstrapOk
= (HANDLE
) 0;
38 HANDLE hSmApiPort
= (HANDLE
) 0;
40 HANDLE hApiPort
= (HANDLE
) 0;
42 /**********************************************************************
43 * CsrpAddInitCompleteProc/1
45 static NTSTATUS FASTCALL
46 CsrpAddInitCompleteProc(CSRPLUGIN_INIT_COMPLETE_PROC Proc
)
48 CSRPLUGIN_INIT_COMPLETE_PROC
*NewProcs
;
50 DPRINT("CSR: %s called\n", __FUNCTION__
);
52 NewProcs
= RtlAllocateHeap(CsrssApiHeap
, 0,
53 (InitCompleteProcCount
+ 1)
54 * sizeof(CSRPLUGIN_INIT_COMPLETE_PROC
));
57 return STATUS_NO_MEMORY
;
59 if (0 != InitCompleteProcCount
)
61 RtlCopyMemory(NewProcs
, InitCompleteProcs
,
62 InitCompleteProcCount
* sizeof(CSRPLUGIN_INIT_COMPLETE_PROC
));
63 RtlFreeHeap(CsrssApiHeap
, 0, InitCompleteProcs
);
65 NewProcs
[InitCompleteProcCount
] = Proc
;
66 InitCompleteProcs
= NewProcs
;
67 InitCompleteProcCount
++;
69 return STATUS_SUCCESS
;
72 static NTSTATUS FASTCALL
73 CsrpAddHardErrorProc(CSRPLUGIN_HARDERROR_PROC Proc
)
75 CSRPLUGIN_HARDERROR_PROC
*NewProcs
;
77 DPRINT("CSR: %s called\n", __FUNCTION__
);
79 NewProcs
= RtlAllocateHeap(CsrssApiHeap
, 0,
80 (HardErrorProcCount
+ 1)
81 * sizeof(CSRPLUGIN_HARDERROR_PROC
));
84 return STATUS_NO_MEMORY
;
86 if (0 != HardErrorProcCount
)
88 RtlCopyMemory(NewProcs
, HardErrorProcs
,
89 HardErrorProcCount
* sizeof(CSRPLUGIN_HARDERROR_PROC
));
90 RtlFreeHeap(CsrssApiHeap
, 0, HardErrorProcs
);
93 NewProcs
[HardErrorProcCount
] = Proc
;
94 HardErrorProcs
= NewProcs
;
97 return STATUS_SUCCESS
;
100 /**********************************************************************
104 CallInitComplete(void)
109 DPRINT("CSR: %s called\n", __FUNCTION__
);
112 if (0 != InitCompleteProcCount
)
114 for (i
= 0; i
< InitCompleteProcCount
&& Ok
; i
++)
116 Ok
= (*(InitCompleteProcs
[i
]))();
118 RtlFreeHeap(CsrssApiHeap
, 0, InitCompleteProcs
);
125 CallHardError(IN PCSRSS_PROCESS_DATA ProcessData
,
126 IN PHARDERROR_MSG HardErrorMessage
)
131 DPRINT("CSR: %s called\n", __FUNCTION__
);
134 if (0 != HardErrorProcCount
)
136 for (i
= 0; i
< HardErrorProcCount
&& Ok
; i
++)
138 Ok
= (*(HardErrorProcs
[i
]))(ProcessData
, HardErrorMessage
);
146 InitializeVideoAddressSpace(VOID
);
148 /**********************************************************************
149 * CsrpCreateObjectDirectory/3
152 CsrpCreateObjectDirectory (int argc
, char ** argv
, char ** envp
)
155 OBJECT_ATTRIBUTES Attributes
;
157 DPRINT("CSR: %s called\n", __FUNCTION__
);
160 /* create object directory ('\Windows') */
161 RtlCreateUnicodeString (&CsrDirectoryName
,
164 InitializeObjectAttributes (&Attributes
,
170 Status
= NtOpenDirectoryObject(&CsrObjectDirectory
,
171 DIRECTORY_ALL_ACCESS
,
176 /**********************************************************************
179 * TODO: we need a virtual device for sessions other than
180 * TODO: the console one
183 CsrpInitVideo (int argc
, char ** argv
, char ** envp
)
185 OBJECT_ATTRIBUTES ObjectAttributes
;
186 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\??\\DISPLAY1");
187 IO_STATUS_BLOCK Iosb
;
188 HANDLE VideoHandle
= (HANDLE
) 0;
189 NTSTATUS Status
= STATUS_SUCCESS
;
191 DPRINT("CSR: %s called\n", __FUNCTION__
);
193 InitializeVideoAddressSpace();
195 InitializeObjectAttributes(&ObjectAttributes
,
200 Status
= NtOpenFile(&VideoHandle
,
206 if (NT_SUCCESS(Status
))
208 NtClose(VideoHandle
);
213 /**********************************************************************
216 * TODO: this function should be turned more general to load an
217 * TODO: hosted server DLL as received from the command line;
218 * TODO: for instance: ServerDll=winsrv:ConServerDllInitialization,2
219 * TODO: ^method ^dll ^api ^sid
221 * TODO: CsrpHostServerDll (LPWSTR DllName,
222 * TODO: LPWSTR ApiName,
223 * TODO: DWORD ServerId)
226 CsrpInitWin32Csr (int argc
, char ** argv
, char ** envp
)
229 UNICODE_STRING DllName
;
231 ANSI_STRING ProcName
;
232 CSRPLUGIN_INITIALIZE_PROC InitProc
;
233 CSRSS_EXPORTED_FUNCS Exports
;
234 PCSRSS_API_DEFINITION ApiDefinitions
;
235 PCSRSS_OBJECT_DEFINITION ObjectDefinitions
;
236 CSRPLUGIN_INIT_COMPLETE_PROC InitCompleteProc
;
237 CSRPLUGIN_HARDERROR_PROC HardErrorProc
;
239 DPRINT("CSR: %s called\n", __FUNCTION__
);
241 RtlInitUnicodeString(&DllName
, L
"win32csr.dll");
242 Status
= LdrLoadDll(NULL
, 0, &DllName
, (PVOID
*) &hInst
);
243 if (! NT_SUCCESS(Status
))
247 RtlInitAnsiString(&ProcName
, "Win32CsrInitialization");
248 Status
= LdrGetProcedureAddress(hInst
, &ProcName
, 0, (PVOID
*) &InitProc
);
249 if (! NT_SUCCESS(Status
))
253 Exports
.CsrInsertObjectProc
= CsrInsertObject
;
254 Exports
.CsrGetObjectProc
= CsrGetObject
;
255 Exports
.CsrReleaseObjectByPointerProc
= CsrReleaseObjectByPointer
;
256 Exports
.CsrReleaseObjectProc
= CsrReleaseObject
;
257 Exports
.CsrEnumProcessesProc
= CsrEnumProcesses
;
258 if (! (*InitProc
)(&ApiDefinitions
, &ObjectDefinitions
, &InitCompleteProc
,
259 &HardErrorProc
, &Exports
, CsrssApiHeap
))
261 return STATUS_UNSUCCESSFUL
;
264 Status
= CsrApiRegisterDefinitions(ApiDefinitions
);
265 if (! NT_SUCCESS(Status
))
269 Status
= CsrRegisterObjectDefinitions(ObjectDefinitions
);
270 if (! NT_SUCCESS(Status
))
274 if (NULL
!= InitCompleteProc
)
276 Status
= CsrpAddInitCompleteProc(InitCompleteProc
);
278 if (HardErrorProc
) Status
= CsrpAddHardErrorProc(HardErrorProc
);
283 CSRSS_API_DEFINITION NativeDefinitions
[] =
285 CSRSS_DEFINE_API(CREATE_PROCESS
, CsrCreateProcess
),
286 CSRSS_DEFINE_API(CREATE_THREAD
, CsrCreateThread
),
287 CSRSS_DEFINE_API(TERMINATE_PROCESS
, CsrTerminateProcess
),
288 CSRSS_DEFINE_API(CONNECT_PROCESS
, CsrConnectProcess
),
289 CSRSS_DEFINE_API(REGISTER_SERVICES_PROCESS
, CsrRegisterServicesProcess
),
290 CSRSS_DEFINE_API(GET_SHUTDOWN_PARAMETERS
, CsrGetShutdownParameters
),
291 CSRSS_DEFINE_API(SET_SHUTDOWN_PARAMETERS
, CsrSetShutdownParameters
),
292 CSRSS_DEFINE_API(GET_INPUT_HANDLE
, CsrGetInputHandle
),
293 CSRSS_DEFINE_API(GET_OUTPUT_HANDLE
, CsrGetOutputHandle
),
294 CSRSS_DEFINE_API(CLOSE_HANDLE
, CsrCloseHandle
),
295 CSRSS_DEFINE_API(VERIFY_HANDLE
, CsrVerifyHandle
),
296 CSRSS_DEFINE_API(DUPLICATE_HANDLE
, CsrDuplicateHandle
),
297 CSRSS_DEFINE_API(GET_INPUT_WAIT_HANDLE
, CsrGetInputWaitHandle
),
301 static NTSTATUS WINAPI
302 CsrpCreateListenPort (IN LPWSTR Name
,
304 IN PTHREAD_START_ROUTINE ListenThread
)
306 NTSTATUS Status
= STATUS_SUCCESS
;
307 OBJECT_ATTRIBUTES PortAttributes
;
308 UNICODE_STRING PortName
;
312 DPRINT("CSR: %s called\n", __FUNCTION__
);
314 RtlInitUnicodeString (& PortName
, Name
);
315 InitializeObjectAttributes (& PortAttributes
,
320 Status
= NtCreatePort ( Port
,
322 LPC_MAX_DATA_LENGTH
, /* TODO: make caller set it*/
323 LPC_MAX_MESSAGE_LENGTH
, /* TODO: make caller set it*/
324 0); /* TODO: make caller set it*/
325 if(!NT_SUCCESS(Status
))
327 DPRINT1("CSR: %s: NtCreatePort failed (Status=%08lx)\n",
328 __FUNCTION__
, Status
);
331 Status
= RtlCreateUserThread(NtCurrentProcess(),
337 (PTHREAD_START_ROUTINE
) ListenThread
,
342 if (ListenThread
== (PVOID
)ClientConnectionThread
)
344 CsrAddStaticServerThread(ServerThread
, &ClientId
, 0);
347 NtResumeThread(ServerThread
, NULL
);
348 NtClose(ServerThread
);
352 /* === INIT ROUTINES === */
354 /**********************************************************************
355 * CsrpCreateBNODirectory/3
357 * These used to be part of kernel32 startup, but that clearly wasn't a good
358 * idea, as races were definately possible. These are moved (as in the
362 CsrpCreateBNODirectory (int argc
, char ** argv
, char ** envp
)
365 OBJECT_ATTRIBUTES ObjectAttributes
;
366 UNICODE_STRING Name
= RTL_CONSTANT_STRING(L
"\\BaseNamedObjects");
367 UNICODE_STRING SymName
= RTL_CONSTANT_STRING(L
"Local");
368 UNICODE_STRING SymName2
= RTL_CONSTANT_STRING(L
"Global");
369 HANDLE DirHandle
, SymHandle
;
371 /* Seems like a good place to create these objects which are needed by
373 InitializeObjectAttributes(&ObjectAttributes
,
375 OBJ_CASE_INSENSITIVE
,
379 Status
= NtCreateDirectoryObject(&DirHandle
,
380 DIRECTORY_ALL_ACCESS
,
382 if (!NT_SUCCESS(Status
))
384 DPRINT1("NtCreateDirectoryObject() failed %08x\n", Status
);
387 /* Create the "local" Symbolic Link.
388 * FIXME: CSR should do this -- Fixed */
389 InitializeObjectAttributes(&ObjectAttributes
,
391 OBJ_CASE_INSENSITIVE
,
394 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
395 SYMBOLIC_LINK_ALL_ACCESS
,
398 if (!NT_SUCCESS(Status
))
400 DPRINT1("NtCreateDirectoryObject() failed %08x\n", Status
);
403 /* Create the "global" Symbolic Link. */
404 InitializeObjectAttributes(&ObjectAttributes
,
406 OBJ_CASE_INSENSITIVE
,
409 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
410 SYMBOLIC_LINK_ALL_ACCESS
,
413 if (!NT_SUCCESS(Status
))
415 DPRINT1("NtCreateDirectoryObject() failed %08x\n", Status
);
421 /**********************************************************************
425 CsrpCreateHeap (int argc
, char ** argv
, char ** envp
)
427 DPRINT("CSR: %s called\n", __FUNCTION__
);
429 CsrssApiHeap
= RtlCreateHeap(HEAP_GROWABLE
,
435 if (CsrssApiHeap
== NULL
)
437 return STATUS_UNSUCCESSFUL
;
439 return STATUS_SUCCESS
;
442 /**********************************************************************
443 * CsrpCreateCallbackPort/3
446 CsrpCreateCallbackPort (int argc
, char ** argv
, char ** envp
)
448 DPRINT("CSR: %s called\n", __FUNCTION__
);
450 return CsrpCreateListenPort (L
"\\Windows\\SbApiPort",
452 ServerSbApiPortThread
);
455 /**********************************************************************
456 * CsrpRegisterSubsystem/3
459 CsrpRegisterSubsystem (int argc
, char ** argv
, char ** envp
)
461 NTSTATUS Status
= STATUS_SUCCESS
;
462 OBJECT_ATTRIBUTES BootstrapOkAttributes
;
465 DPRINT("CSR: %s called\n", __FUNCTION__
);
468 * Create the event object the callback port
469 * thread will signal *if* the SM will
470 * authorize us to bootstrap.
472 RtlInitUnicodeString (& Name
, L
"\\CsrssBooting");
473 InitializeObjectAttributes(& BootstrapOkAttributes
,
476 Status
= NtCreateEvent (& hBootstrapOk
,
478 & BootstrapOkAttributes
,
479 SynchronizationEvent
,
481 if(!NT_SUCCESS(Status
))
483 DPRINT("CSR: %s: NtCreateEvent failed (Status=0x%08lx)\n",
484 __FUNCTION__
, Status
);
488 * Let's tell the SM a new environment
489 * subsystem server is in the system.
491 RtlInitUnicodeString (& Name
, L
"\\Windows\\SbApiPort");
492 DPRINT("CSR: %s: registering with SM for\n IMAGE_SUBSYSTEM_WINDOWS_CUI == 3\n", __FUNCTION__
);
493 Status
= SmConnectApiPort (& Name
,
495 IMAGE_SUBSYSTEM_WINDOWS_CUI
,
497 if(!NT_SUCCESS(Status
))
499 DPRINT("CSR: %s unable to connect to the SM (Status=0x%08lx)\n",
500 __FUNCTION__
, Status
);
501 NtClose (hBootstrapOk
);
505 * Wait for SM to reply OK... If the SM
506 * won't answer, we hang here forever!
508 DPRINT("CSR: %s: waiting for SM to OK boot...\n", __FUNCTION__
);
509 Status
= NtWaitForSingleObject (hBootstrapOk
,
512 NtClose (hBootstrapOk
);
516 /**********************************************************************
517 * EnvpToUnicodeString/2
519 static ULONG FASTCALL
520 EnvpToUnicodeString (char ** envp
, PUNICODE_STRING UnicodeEnv
)
526 UnicodeEnv
->Buffer
= NULL
;
528 for (Index
=0; NULL
!= envp
[Index
]; Index
++)
530 CharCount
+= strlen (envp
[Index
]);
535 AnsiEnv
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap(), 0, CharCount
);
536 if (NULL
!= AnsiEnv
.Buffer
)
539 PCHAR WritePos
= AnsiEnv
.Buffer
;
541 for (Index
=0; NULL
!= envp
[Index
]; Index
++)
543 strcpy (WritePos
, envp
[Index
]);
544 WritePos
+= strlen (envp
[Index
]) + 1;
547 /* FIXME: the last (double) nullterm should perhaps not be included in Length
548 * but only in MaximumLength. -Gunnar */
549 AnsiEnv
.Buffer
[CharCount
-1] = '\0';
550 AnsiEnv
.Length
= CharCount
;
551 AnsiEnv
.MaximumLength
= CharCount
;
553 RtlAnsiStringToUnicodeString (UnicodeEnv
, & AnsiEnv
, TRUE
);
554 RtlFreeHeap (RtlGetProcessHeap(), 0, AnsiEnv
.Buffer
);
558 /**********************************************************************
559 * CsrpLoadKernelModeDriver/3
562 CsrpLoadKernelModeDriver (int argc
, char ** argv
, char ** envp
)
564 NTSTATUS Status
= STATUS_SUCCESS
;
565 WCHAR Data
[MAX_PATH
+ 1];
566 ULONG DataLength
= sizeof Data
;
568 UNICODE_STRING Environment
;
571 DPRINT("SM: %s called\n", __FUNCTION__
);
574 EnvpToUnicodeString (envp
, & Environment
);
575 Status
= SmLookupSubsystem (L
"Kmode",
580 RtlFreeUnicodeString (& Environment
);
581 if((STATUS_SUCCESS
== Status
) && (DataLength
> sizeof Data
[0]))
583 WCHAR ImagePath
[MAX_PATH
+ 1] = {0};
584 UNICODE_STRING ModuleName
;
586 wcscpy (ImagePath
, L
"\\??\\");
587 wcscat (ImagePath
, Data
);
588 RtlInitUnicodeString (& ModuleName
, ImagePath
);
589 Status
= NtSetSystemInformation(/* FIXME: SystemLoadAndCallImage */
590 SystemExtendServiceTableInformation
,
593 if(!NT_SUCCESS(Status
))
595 DPRINT("WIN: %s: loading Kmode failed (Status=0x%08lx)\n",
596 __FUNCTION__
, Status
);
602 /**********************************************************************
603 * CsrpCreateApiPort/2
606 CsrpCreateApiPort (int argc
, char ** argv
, char ** envp
)
608 DPRINT("CSR: %s called\n", __FUNCTION__
);
610 CsrInitProcessData();
612 return CsrpCreateListenPort(L
"\\Windows\\ApiPort", &hApiPort
,
613 (PTHREAD_START_ROUTINE
)ClientConnectionThread
);
616 /**********************************************************************
617 * CsrpApiRegisterDef/0
620 CsrpApiRegisterDef (int argc
, char ** argv
, char ** envp
)
622 return CsrApiRegisterDefinitions(NativeDefinitions
);
625 /**********************************************************************
629 CsrpCCTS (int argc
, char ** argv
, char ** envp
)
632 ULONG DummyLength
= sizeof(Dummy
);
633 return CsrClientConnectToServer(L
"\\Windows",
634 0, &Dummy
, &DummyLength
, NULL
);
637 /**********************************************************************
640 * Start the logon process (winlogon.exe).
642 * TODO: this should be moved in CsrpCreateSession/x (one per session)
643 * TODO: in its own desktop (one logon desktop per winstation).
646 CsrpRunWinlogon (int argc
, char ** argv
, char ** envp
)
648 NTSTATUS Status
= STATUS_SUCCESS
;
649 UNICODE_STRING ImagePath
;
650 UNICODE_STRING CommandLine
;
651 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
652 RTL_USER_PROCESS_INFORMATION ProcessInfo
;
655 DPRINT("CSR: %s called\n", __FUNCTION__
);
657 /* initialize the process parameters */
658 RtlInitUnicodeString (& ImagePath
, L
"\\SystemRoot\\system32\\winlogon.exe");
659 RtlInitUnicodeString (& CommandLine
, L
"");
660 RtlCreateProcessParameters(& ProcessParameters
,
670 /* Create the winlogon process */
671 Status
= RtlCreateUserProcess (& ImagePath
,
672 OBJ_CASE_INSENSITIVE
,
682 RtlDestroyProcessParameters (ProcessParameters
);
683 if (!NT_SUCCESS(Status
))
685 DPRINT1("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
686 __FUNCTION__
, Status
);
689 ZwResumeThread(ProcessInfo
.ThreadHandle
, NULL
);
694 CsrpCreateHardErrorPort (int argc
, char ** argv
, char ** envp
)
696 return NtSetDefaultHardErrorPort(hApiPort
);
699 typedef NTSTATUS (* CSR_INIT_ROUTINE
)(int,char**,char**);
703 CSR_INIT_ROUTINE EntryPoint
;
706 {TRUE
, CsrpCreateBNODirectory
, "create base named objects directory"},
707 {TRUE
, CsrpCreateCallbackPort
, "create the callback port \\Windows\\SbApiPort"},
708 {TRUE
, CsrpRegisterSubsystem
, "register with SM"},
709 {TRUE
, CsrpCreateHeap
, "create the CSR heap"},
710 {TRUE
, CsrpCreateApiPort
, "create the api port \\Windows\\ApiPort"},
711 {TRUE
, CsrpCreateHardErrorPort
, "create the hard error port"},
712 {TRUE
, CsrpCreateObjectDirectory
,"create the object directory \\Windows"},
713 {TRUE
, CsrpLoadKernelModeDriver
, "load Kmode driver"},
714 {TRUE
, CsrpInitVideo
, "initialize video"},
715 {TRUE
, CsrpApiRegisterDef
, "initialize api definitions"},
716 {TRUE
, CsrpCCTS
, "connect client to server"},
717 {TRUE
, CsrpInitWin32Csr
, "load usermode dll"},
718 {TRUE
, CsrpRunWinlogon
, "run WinLogon"},
721 /**********************************************************************
723 * CsrServerInitialization
726 * Initialize the Win32 environment subsystem server.
729 * TRUE: Initialization OK; otherwise FALSE.
732 CsrServerInitialization (
739 NTSTATUS Status
= STATUS_SUCCESS
;
741 DPRINT("CSR: %s called\n", __FUNCTION__
);
743 for (i
=0; i
< (sizeof InitRoutine
/ sizeof InitRoutine
[0]); i
++)
745 Status
= InitRoutine
[i
].EntryPoint(argc
,argv
,envp
);
746 if(!NT_SUCCESS(Status
))
748 DPRINT1("CSR: %s: failed to %s (Status=%08lx)\n",
750 InitRoutine
[i
].ErrorMessage
,
752 if (InitRoutine
[i
].Required
)
758 if (CallInitComplete())
760 Status
= SmCompleteSession (hSmApiPort
,hSbApiPort
,hApiPort
);