2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Client/Server Runtime SubSystem
4 * FILE: subsystems/win32/csrsrv/init.c
5 * PURPOSE: CSR Server DLL Initialization
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * ReactOS Portable Systems Group
10 /* INCLUDES *******************************************************************/
17 /* DATA ***********************************************************************/
19 HANDLE CsrHeap
= NULL
;
20 HANDLE CsrObjectDirectory
= NULL
;
21 UNICODE_STRING CsrDirectoryName
;
22 UNICODE_STRING CsrSbApiPortName
;
23 HANDLE CsrSbApiPort
= NULL
;
24 PCSR_THREAD CsrSbApiRequestThreadPtr
;
25 HANDLE CsrSmApiPort
= NULL
;
26 HANDLE hSbApiPort
= NULL
;
27 HANDLE CsrApiPort
= NULL
;
28 ULONG CsrDebug
= 0; // 0xFFFFFFFF;
29 ULONG CsrMaxApiRequestThreads
;
30 ULONG CsrTotalPerProcessDataLength
;
32 HANDLE BNOLinksDirectory
;
33 HANDLE SessionObjectDirectory
;
34 HANDLE DosDevicesDirectory
;
35 HANDLE CsrInitializationEvent
;
36 SYSTEM_BASIC_INFORMATION CsrNtSysInfo
;
39 /* PRIVATE FUNCTIONS **********************************************************/
41 /* === INIT ROUTINES === */
44 * @name CsrSetProcessSecurity
46 * The CsrSetProcessSecurity routine protects access to the CSRSS process
47 * from unauthorized tampering.
51 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
58 CsrSetProcessSecurity(VOID
)
61 HANDLE hToken
, hProcess
= NtCurrentProcess();
63 PTOKEN_USER TokenInfo
= NULL
;
64 PSECURITY_DESCRIPTOR ProcSd
= NULL
;
69 Status
= NtOpenProcessToken(hProcess
, TOKEN_QUERY
, &hToken
);
70 if (!NT_SUCCESS(Status
)) goto Quickie
;
72 /* Get the Token User Length */
73 NtQueryInformationToken(hToken
, TokenUser
, NULL
, 0, &Length
);
75 /* Allocate space for it */
76 TokenInfo
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Length
);
79 Status
= STATUS_NO_MEMORY
;
83 /* Now query the data */
84 Status
= NtQueryInformationToken(hToken
, TokenUser
, TokenInfo
, Length
, &Length
);
86 if (!NT_SUCCESS(Status
)) goto Quickie
;
88 /* Now check the SID Length */
89 UserSid
= TokenInfo
->User
.Sid
;
90 Length
= RtlLengthSid(UserSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
92 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
93 ProcSd
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
96 Status
= STATUS_NO_MEMORY
;
100 /* Set the pointer to the DACL */
101 Dacl
= (PACL
)((ULONG_PTR
)ProcSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
103 /* Now create the SD itself */
104 Status
= RtlCreateSecurityDescriptor(ProcSd
, SECURITY_DESCRIPTOR_REVISION
);
105 if (!NT_SUCCESS(Status
))
107 DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status
);
111 /* Create the DACL for it*/
112 Status
= RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
113 if (!NT_SUCCESS(Status
))
115 DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status
);
120 Status
= RtlAddAccessAllowedAce(Dacl
,
122 PROCESS_VM_READ
| PROCESS_VM_WRITE
|
123 PROCESS_VM_OPERATION
| PROCESS_DUP_HANDLE
|
124 PROCESS_TERMINATE
| PROCESS_SUSPEND_RESUME
|
125 PROCESS_QUERY_INFORMATION
| READ_CONTROL
,
127 if (!NT_SUCCESS(Status
))
129 DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status
);
133 /* Clear the DACL in the SD */
134 Status
= RtlSetDaclSecurityDescriptor(ProcSd
, TRUE
, Dacl
, FALSE
);
135 if (!NT_SUCCESS(Status
))
137 DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status
);
141 /* Write the SD into the Process */
142 Status
= NtSetSecurityObject(hProcess
, DACL_SECURITY_INFORMATION
, ProcSd
);
143 if (!NT_SUCCESS(Status
))
145 DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status
);
149 /* Free the memory and return */
151 if (ProcSd
) RtlFreeHeap(CsrHeap
, 0, ProcSd
);
152 RtlFreeHeap(CsrHeap
, 0, TokenInfo
);
157 * @name CsrSetDirectorySecurity
159 * The CsrSetDirectorySecurity routine sets the security descriptor for the
160 * specified Object Directory.
162 * @param ObjectDirectory
163 * Handle fo the Object Directory to protect.
165 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
172 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory
)
174 /* FIXME: Implement */
175 return STATUS_SUCCESS
;
179 * @name GetDosDevicesProtection
181 * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
184 * @param DosDevicesSd
185 * Pointer to the Security Descriptor to return.
187 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
189 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
190 * regular users may or may not have full access to the directory.
195 GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd
)
197 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
198 SID_IDENTIFIER_AUTHORITY CreatorAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
199 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
200 PSID WorldSid
, CreatorSid
, AdminSid
, SystemSid
;
201 UCHAR KeyValueBuffer
[0x40];
202 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
203 UNICODE_STRING KeyName
;
204 ULONG ProtectionMode
= 0;
205 OBJECT_ATTRIBUTES ObjectAttributes
;
207 PACCESS_ALLOWED_ACE Ace
;
210 ULONG ResultLength
, SidLength
, AclLength
;
213 Status
= RtlCreateSecurityDescriptor(DosDevicesSd
, SECURITY_DESCRIPTOR_REVISION
);
214 ASSERT(NT_SUCCESS(Status
));
216 /* Initialize the System SID */
217 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
218 SECURITY_LOCAL_SYSTEM_RID
,
221 ASSERT(NT_SUCCESS(Status
));
223 /* Initialize the World SID */
224 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
, 1,
228 ASSERT(NT_SUCCESS(Status
));
230 /* Initialize the Admin SID */
231 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 2,
232 SECURITY_BUILTIN_DOMAIN_RID
,
233 DOMAIN_ALIAS_RID_ADMINS
,
236 ASSERT(NT_SUCCESS(Status
));
238 /* Initialize the Creator SID */
239 Status
= RtlAllocateAndInitializeSid(&CreatorAuthority
, 1,
240 SECURITY_CREATOR_OWNER_RID
,
243 ASSERT(NT_SUCCESS(Status
));
245 /* Open the Session Manager Key */
246 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
247 InitializeObjectAttributes(&ObjectAttributes
,
249 OBJ_CASE_INSENSITIVE
,
252 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
253 if (NT_SUCCESS(Status
))
255 /* Read the key value */
256 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
257 Status
= NtQueryValueKey(hKey
,
259 KeyValuePartialInformation
,
261 sizeof(KeyValueBuffer
),
264 /* Make sure it's what we expect it to be */
265 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
266 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
267 (*(PULONG
)KeyValuePartialInfo
->Data
))
269 /* Save the Protection Mode */
270 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
273 /* Close the handle */
277 /* Check the Protection Mode */
278 if (ProtectionMode
& 3)
280 /* Calculate SID Lengths */
281 SidLength
= RtlLengthSid(CreatorSid
) + RtlLengthSid(SystemSid
) +
282 RtlLengthSid(AdminSid
);
283 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
285 /* Allocate memory for the DACL */
286 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
287 ASSERT(Dacl
!= NULL
);
289 /* Build the ACL and add 3 ACEs */
290 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
291 ASSERT(NT_SUCCESS(Status
));
292 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
293 ASSERT(NT_SUCCESS(Status
));
294 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, AdminSid
);
295 ASSERT(NT_SUCCESS(Status
));
296 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, CreatorSid
);
297 ASSERT(NT_SUCCESS(Status
));
299 /* Edit the ACEs to make them inheritable */
300 Status
= RtlGetAce(Dacl
, 0, (PVOID
*)&Ace
);
301 ASSERT(NT_SUCCESS(Status
));
302 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
303 Status
= RtlGetAce(Dacl
, 1, (PVOID
*)&Ace
);
304 ASSERT(NT_SUCCESS(Status
));
305 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
306 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
307 ASSERT(NT_SUCCESS(Status
));
308 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
310 /* Set this DACL with the SD */
311 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
312 ASSERT(NT_SUCCESS(Status
));
317 /* Calculate SID Lengths */
318 SidLength
= RtlLengthSid(WorldSid
) + RtlLengthSid(SystemSid
);
319 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
321 /* Allocate memory for the DACL */
322 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
323 ASSERT(Dacl
!= NULL
);
325 /* Build the ACL and add 3 ACEs */
326 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
327 ASSERT(NT_SUCCESS(Status
));
328 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
, WorldSid
);
329 ASSERT(NT_SUCCESS(Status
));
330 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
331 ASSERT(NT_SUCCESS(Status
));
332 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, WorldSid
);
333 ASSERT(NT_SUCCESS(Status
));
335 /* Edit the last ACE to make it inheritable */
336 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
337 ASSERT(NT_SUCCESS(Status
));
338 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
340 /* Set this DACL with the SD */
341 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
342 ASSERT(NT_SUCCESS(Status
));
346 /* FIXME: failure cases! Fail: */
347 /* Free the memory */
348 RtlFreeHeap(CsrHeap
, 0, Dacl
);
350 /* FIXME: semi-failure cases! Quickie: */
353 RtlFreeSid(CreatorSid
);
354 RtlFreeSid(AdminSid
);
355 RtlFreeSid(WorldSid
);
356 RtlFreeSid(SystemSid
);
363 * @name FreeDosDevicesProtection
365 * The FreeDosDevicesProtection frees the security descriptor that was created
366 * by GetDosDevicesProtection
368 * @param DosDevicesSd
369 * Pointer to the security descriptor to free.
378 FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd
)
381 BOOLEAN Present
, Default
;
384 /* Get the DACL corresponding to this SD */
385 Status
= RtlGetDaclSecurityDescriptor(DosDevicesSd
, &Present
, &Dacl
, &Default
);
386 ASSERT(NT_SUCCESS(Status
));
388 ASSERT(Dacl
!= NULL
);
391 if ((NT_SUCCESS(Status
)) && (Dacl
)) RtlFreeHeap(CsrHeap
, 0, Dacl
);
395 * @name CsrCreateSessionObjectDirectory
397 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
398 * Session and Dos Devices directories for the specified session.
401 * Session ID for which to create the directories.
403 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
410 CsrCreateSessionObjectDirectory(IN ULONG Session
)
412 WCHAR SessionBuffer
[512], BnoBuffer
[512];
413 UNICODE_STRING SessionString
, BnoString
;
414 OBJECT_ATTRIBUTES ObjectAttributes
;
416 SECURITY_DESCRIPTOR DosDevicesSd
;
419 /* Generate the Session BNOLINKS Directory name */
420 swprintf(SessionBuffer
, L
"%ws\\BNOLINKS", SESSION_ROOT
);
421 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
424 InitializeObjectAttributes(&ObjectAttributes
,
426 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
429 Status
= NtCreateDirectoryObject(&BNOLinksDirectory
,
430 DIRECTORY_ALL_ACCESS
,
432 if (!NT_SUCCESS(Status
))
434 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
435 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
439 /* Now add the Session ID */
440 swprintf(SessionBuffer
, L
"%ld", Session
);
441 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
443 /* Check if this is the first Session */
446 /* Not the first, so the name will be slighly more complex */
447 swprintf(BnoBuffer
, L
"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT
, Session
);
448 RtlInitUnicodeString(&BnoString
, BnoBuffer
);
452 /* Use the direct name */
453 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
456 /* Create the symlink */
457 InitializeObjectAttributes(&ObjectAttributes
,
459 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
462 Status
= NtCreateSymbolicLinkObject(&BnoHandle
,
463 SYMBOLIC_LINK_ALL_ACCESS
,
466 if (!NT_SUCCESS(Status
))
468 DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
469 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
473 /* Create the \DosDevices Security Descriptor */
474 Status
= GetDosDevicesProtection(&DosDevicesSd
);
475 if (!NT_SUCCESS(Status
)) return Status
;
477 /* Now create a directory for this session */
478 swprintf(SessionBuffer
, L
"%ws\\%ld", SESSION_ROOT
, Session
);
479 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
481 /* Create the directory */
482 InitializeObjectAttributes(&ObjectAttributes
,
484 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
487 Status
= NtCreateDirectoryObject(&SessionObjectDirectory
,
488 DIRECTORY_ALL_ACCESS
,
490 if (!NT_SUCCESS(Status
))
492 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
493 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
494 FreeDosDevicesProtection(&DosDevicesSd
);
498 /* Next, create a directory for this session's DOS Devices */
499 RtlInitUnicodeString(&SessionString
, L
"DosDevices");
500 InitializeObjectAttributes(&ObjectAttributes
,
502 OBJ_CASE_INSENSITIVE
,
503 SessionObjectDirectory
,
505 Status
= NtCreateDirectoryObject(&DosDevicesDirectory
,
506 DIRECTORY_ALL_ACCESS
,
508 if (!NT_SUCCESS(Status
))
510 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
511 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
514 /* Release the Security Descriptor */
515 FreeDosDevicesProtection(&DosDevicesSd
);
522 * @name CsrParseServerCommandLine
524 * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
525 * registry and performs operations for each entry found.
527 * @param ArgumentCount
528 * Number of arguments on the command line.
531 * Array of arguments.
533 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
540 CsrParseServerCommandLine(IN ULONG ArgumentCount
,
541 IN PCHAR Arguments
[])
544 PCHAR ParameterName
= NULL
, ParameterValue
= NULL
, EntryPoint
, ServerString
;
546 ANSI_STRING AnsiString
;
547 OBJECT_ATTRIBUTES ObjectAttributes
;
549 /* Set the Defaults */
550 CsrTotalPerProcessDataLength
= 0;
551 CsrObjectDirectory
= NULL
;
552 CsrMaxApiRequestThreads
= 16;
554 /* Save our Session ID, and create a Directory for it */
555 SessionId
= NtCurrentPeb()->SessionId
;
556 Status
= CsrCreateSessionObjectDirectory(SessionId
);
557 if (!NT_SUCCESS(Status
))
559 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
562 /* It's not fatal if the session ID isn't zero */
563 if (SessionId
!= 0) return Status
;
564 ASSERT(NT_SUCCESS(Status
));
567 /* Loop through every argument */
568 for (i
= 1; i
< ArgumentCount
; i
++)
570 /* Split Name and Value */
571 ParameterName
= Arguments
[i
];
572 ParameterValue
= NULL
;
573 ParameterValue
= strchr(ParameterName
, '=');
574 if (ParameterValue
) *ParameterValue
++ = ANSI_NULL
;
575 DPRINT1("Name=%s, Value=%s\n", ParameterName
, ParameterValue
);
577 /* Check for Object Directory */
578 if (_stricmp(ParameterName
, "ObjectDirectory") == 0)
580 /* Check if a session ID is specified */
583 DPRINT1("Sessions not yet implemented\n");
587 /* Initialize the directory name */
588 RtlInitAnsiString(&AnsiString
, ParameterValue
);
589 Status
= RtlAnsiStringToUnicodeString(&CsrDirectoryName
,
592 ASSERT(NT_SUCCESS(Status
) || SessionId
!= 0);
593 if (!NT_SUCCESS(Status
)) return Status
;
596 InitializeObjectAttributes(&ObjectAttributes
,
598 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
601 Status
= NtCreateDirectoryObject(&CsrObjectDirectory
,
602 DIRECTORY_ALL_ACCESS
,
604 if (!NT_SUCCESS(Status
)) return Status
;
607 Status
= CsrSetDirectorySecurity(CsrObjectDirectory
);
608 if (!NT_SUCCESS(Status
)) return Status
;
610 else if (_stricmp(ParameterName
, "SubSystemType") == 0)
614 else if (_stricmp(ParameterName
, "MaxRequestThreads") == 0)
616 Status
= RtlCharToInteger(ParameterValue
,
618 &CsrMaxApiRequestThreads
);
620 else if (_stricmp(ParameterName
, "RequestThreads") == 0)
623 Status
= STATUS_SUCCESS
;
625 else if (_stricmp(ParameterName
, "ProfileControl") == 0)
629 else if (_stricmp(ParameterName
, "SharedSection") == 0)
631 /* Create the Section */
632 Status
= CsrSrvCreateSharedSection(ParameterValue
);
633 if (!NT_SUCCESS(Status
))
635 DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
636 ParameterName
, ParameterValue
, Status
);
641 Status
= CsrLoadServerDll("CSRSS" /* "CSRSRV" */, NULL
, CSRSRV_SERVERDLL_INDEX
);
643 else if (_stricmp(ParameterName
, "ServerDll") == 0)
645 /* Loop the command line */
647 Status
= STATUS_INVALID_PARAMETER
;
648 ServerString
= ParameterValue
;
649 while (*ServerString
)
651 /* Check for the Entry Point */
652 if ((*ServerString
== ':') && (!EntryPoint
))
654 /* Found it. Add a nullchar and save it */
655 *ServerString
++ = ANSI_NULL
;
656 EntryPoint
= ServerString
;
659 /* Check for the Dll Index */
660 if (*ServerString
++ == ',') break;
663 /* Did we find something to load? */
666 DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
667 ParameterValue
, Status
);
671 /* Convert it to a ULONG */
672 Status
= RtlCharToInteger(ServerString
, 10, &DllIndex
);
674 /* Add a null char if it was valid */
675 if (NT_SUCCESS(Status
)) ServerString
[-1] = ANSI_NULL
;
678 if (CsrDebug
& 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue
, EntryPoint
);
679 Status
= CsrLoadServerDll(ParameterValue
, EntryPoint
, DllIndex
);
680 if (!NT_SUCCESS(Status
))
682 DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
683 ParameterValue
, Status
);
687 else if (_stricmp(ParameterName
, "Windows") == 0)
690 // Check whether we want to start in pure GUI or pure CLI.
694 /* Invalid parameter on the command line */
695 Status
= STATUS_INVALID_PARAMETER
;
704 * @name CsrInitCsrRootProcess
706 * The CsrInitCsrRootProcess routine further initializes the CSR Root Process
707 * created by CsrInitializeProcessStructure, by allocating and initializing
708 * per-process data for each Server DLL.
712 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
719 CsrInitCsrRootProcess(VOID
)
722 PCSR_SERVER_DLL ServerDll
;
725 /* All Server DLLs are now loaded, allocate a heap for the Root Process */
726 ProcessData
= RtlAllocateHeap(CsrHeap
,
728 CsrTotalPerProcessDataLength
);
731 DPRINT1("CSRSRV:%s: RtlAllocateHeap failed (Status=%08lx)\n",
732 __FUNCTION__
, STATUS_NO_MEMORY
);
733 return STATUS_NO_MEMORY
;
737 * Our Root Process was never officially initialized,
738 * so write the data for each Server DLL manually.
742 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
744 /* Get the current Server */
745 ServerDll
= CsrLoadedServerDll
[i
];
747 /* Is it loaded, and does it have per process data? */
748 if (ServerDll
&& ServerDll
->SizeOfProcessData
)
750 /* It does, give it part of our allocated heap */
751 CsrRootProcess
->ServerData
[i
] = ProcessData
;
753 /* Move to the next heap position */
754 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
755 ServerDll
->SizeOfProcessData
);
759 /* Nothing for this Server DLL */
760 CsrRootProcess
->ServerData
[i
] = NULL
;
764 /* Now initialize the Root Process manually as well */
765 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
767 /* Get the current Server */
768 ServerDll
= CsrLoadedServerDll
[i
];
770 /* Is it loaded, and does it a callback for new processes? */
771 if (ServerDll
&& ServerDll
->NewProcessCallback
)
773 /* Call the callback */
774 ServerDll
->NewProcessCallback(NULL
, CsrRootProcess
);
778 return STATUS_SUCCESS
;
782 * @name CsrCreateLocalSystemSD
784 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
785 * the local account with PORT_ALL_ACCESS.
787 * @param LocalSystemSd
788 * Pointer to a pointer to the security descriptor to create.
790 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
797 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR
*LocalSystemSd
)
799 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
802 PSECURITY_DESCRIPTOR SystemSd
;
806 /* Initialize the System SID */
807 RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
808 SECURITY_LOCAL_SYSTEM_RID
,
812 /* Get the length of the SID */
813 Length
= RtlLengthSid(SystemSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
815 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
816 SystemSd
= RtlAllocateHeap(CsrHeap
, 0, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
818 /* Set the pointer to the DACL */
819 Dacl
= (PACL
)((ULONG_PTR
)SystemSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
821 /* Now create the SD itself */
822 Status
= RtlCreateSecurityDescriptor(SystemSd
, SECURITY_DESCRIPTOR_REVISION
);
823 if (!NT_SUCCESS(Status
)) goto Quit
;
825 /* Create the DACL for it */
826 RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
829 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, PORT_ALL_ACCESS
, SystemSid
);
830 if (!NT_SUCCESS(Status
)) goto Quit
;
832 /* Clear the DACL in the SD */
833 Status
= RtlSetDaclSecurityDescriptor(SystemSd
, TRUE
, Dacl
, FALSE
);
834 if (!NT_SUCCESS(Status
)) goto Quit
;
837 if (!NT_SUCCESS(Status
))
839 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
843 /* Free the SID and return*/
844 RtlFreeSid(SystemSid
);
845 *LocalSystemSd
= SystemSd
;
850 * @name CsrSbApiPortInitialize
852 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
853 * communications with the Session Manager (SM) and initializes the static
854 * thread that will handle connection requests and APIs.
858 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
865 CsrSbApiPortInitialize(VOID
)
868 PSECURITY_DESCRIPTOR PortSd
;
869 OBJECT_ATTRIBUTES ObjectAttributes
;
871 HANDLE hRequestThread
;
874 /* Calculate how much space we'll need for the Port Name */
875 Size
= CsrDirectoryName
.Length
+ sizeof(SB_PORT_NAME
) + sizeof(WCHAR
);
877 /* Create the buffer for it */
878 CsrSbApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
879 if (!CsrSbApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
881 /* Setup the rest of the empty string */
882 CsrSbApiPortName
.Length
= 0;
883 CsrSbApiPortName
.MaximumLength
= (USHORT
)Size
;
885 /* Now append the full port name */
886 RtlAppendUnicodeStringToString(&CsrSbApiPortName
, &CsrDirectoryName
);
887 RtlAppendUnicodeToString(&CsrSbApiPortName
, UNICODE_PATH_SEP
);
888 RtlAppendUnicodeToString(&CsrSbApiPortName
, SB_PORT_NAME
);
889 if (CsrDebug
& 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName
);
891 /* Create Security Descriptor for this Port */
892 Status
= CsrCreateLocalSystemSD(&PortSd
);
893 if (!NT_SUCCESS(Status
)) return Status
;
895 /* Initialize the Attributes */
896 InitializeObjectAttributes(&ObjectAttributes
,
902 /* Create the Port Object */
903 Status
= NtCreatePort(&CsrSbApiPort
,
905 sizeof(SB_CONNECTION_INFO
),
907 32 * sizeof(SB_API_MSG
));
908 if (PortSd
) RtlFreeHeap(CsrHeap
, 0, PortSd
);
910 if (NT_SUCCESS(Status
))
912 /* Create the Thread to handle the API Requests */
913 Status
= RtlCreateUserThread(NtCurrentProcess(),
919 (PVOID
)CsrSbApiRequestThread
,
923 if (NT_SUCCESS(Status
))
925 /* Add it as a Static Server Thread */
926 CsrSbApiRequestThreadPtr
= CsrAddStaticServerThread(hRequestThread
,
931 Status
= NtResumeThread(hRequestThread
, NULL
);
939 /* PUBLIC FUNCTIONS ***********************************************************/
942 * @name CsrServerInitialization
945 * The CsrServerInitialization routine is the native (not Server) entrypoint
946 * of this Server DLL. It serves as the entrypoint for CSRSS.
948 * @param ArgumentCount
949 * Number of arguments on the command line.
952 * Array of arguments from the command line.
954 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
961 CsrServerInitialization(IN ULONG ArgumentCount
,
962 IN PCHAR Arguments
[])
964 NTSTATUS Status
= STATUS_SUCCESS
;
966 /* Create the Init Event */
967 Status
= NtCreateEvent(&CsrInitializationEvent
,
970 SynchronizationEvent
,
972 if (!NT_SUCCESS(Status
))
974 DPRINT1("CSRSRV:%s: NtCreateEvent failed (Status=%08lx)\n",
975 __FUNCTION__
, Status
);
979 /* Cache System Basic Information so we don't always request it */
980 Status
= NtQuerySystemInformation(SystemBasicInformation
,
982 sizeof(SYSTEM_BASIC_INFORMATION
),
984 if (!NT_SUCCESS(Status
))
986 DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=%08lx)\n",
987 __FUNCTION__
, Status
);
992 CsrHeap
= RtlGetProcessHeap();
994 /* Set our Security Descriptor to protect the process */
995 Status
= CsrSetProcessSecurity();
996 if (!NT_SUCCESS(Status
))
998 DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=%08lx)\n",
999 __FUNCTION__
, Status
);
1003 /* Set up Session Support */
1004 Status
= CsrInitializeNtSessionList();
1005 if (!NT_SUCCESS(Status
))
1007 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
1008 __FUNCTION__
, Status
);
1012 /* Set up Process Support and allocate the CSR Root Process */
1013 Status
= CsrInitializeProcessStructure();
1014 if (!NT_SUCCESS(Status
))
1016 DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=%08lx)\n",
1017 __FUNCTION__
, Status
);
1021 /* Parse the command line */
1022 Status
= CsrParseServerCommandLine(ArgumentCount
, Arguments
);
1023 if (!NT_SUCCESS(Status
))
1025 DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=%08lx)\n",
1026 __FUNCTION__
, Status
);
1030 /* Finish to initialize the CSR Root Process */
1031 Status
= CsrInitCsrRootProcess();
1032 if (!NT_SUCCESS(Status
))
1034 DPRINT1("CSRSRV:%s: CsrInitCsrRootProcess failed (Status=%08lx)\n",
1035 __FUNCTION__
, Status
);
1039 /* Now initialize our API Port */
1040 Status
= CsrApiPortInitialize();
1041 if (!NT_SUCCESS(Status
))
1043 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n",
1044 __FUNCTION__
, Status
);
1048 /* Initialize the API Port for SM communication */
1049 Status
= CsrSbApiPortInitialize();
1050 if (!NT_SUCCESS(Status
))
1052 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n",
1053 __FUNCTION__
, Status
);
1057 /* We're all set! Connect to SM! */
1058 Status
= SmConnectToSm(&CsrSbApiPortName
,
1060 IMAGE_SUBSYSTEM_WINDOWS_GUI
,
1062 if (!NT_SUCCESS(Status
))
1064 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n",
1065 __FUNCTION__
, Status
);
1069 /* Finito! Signal the event */
1070 Status
= NtSetEvent(CsrInitializationEvent
, NULL
);
1071 if (!NT_SUCCESS(Status
))
1073 DPRINT1("CSRSRV:%s: NtSetEvent failed (Status=%08lx)\n",
1074 __FUNCTION__
, Status
);
1078 /* Close the event handle now */
1079 NtClose(CsrInitializationEvent
);
1081 /* Have us handle Hard Errors */
1082 Status
= NtSetDefaultHardErrorPort(CsrApiPort
);
1083 if (!NT_SUCCESS(Status
))
1085 DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n",
1086 __FUNCTION__
, Status
);
1095 * @name CsrPopulateDosDevices
1096 * @unimplemented NT5.1
1098 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1099 * to populate the Dos Devices Object Directory for the session.
1110 CsrPopulateDosDevices(VOID
)
1112 DPRINT1("Deprecated API in r55585.\n");
1118 DllMain(IN HINSTANCE hInstanceDll
,
1120 IN LPVOID lpReserved
)
1122 /* We don't do much */
1123 UNREFERENCED_PARAMETER(hInstanceDll
);
1124 UNREFERENCED_PARAMETER(dwReason
);
1125 UNREFERENCED_PARAMETER(lpReserved
);