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 *******************************************************************/
15 #include <ndk/cmfuncs.h>
20 /* DATA ***********************************************************************/
23 ULONG CsrDebug
= 0; // 0xFFFFFFFF;
25 HANDLE CsrHeap
= NULL
;
26 HANDLE CsrObjectDirectory
= NULL
;
27 UNICODE_STRING CsrDirectoryName
;
28 UNICODE_STRING CsrSbApiPortName
;
29 HANDLE CsrSbApiPort
= NULL
;
30 PCSR_THREAD CsrSbApiRequestThreadPtr
;
31 HANDLE CsrSmApiPort
= NULL
;
32 HANDLE hSbApiPort
= NULL
;
33 HANDLE CsrApiPort
= NULL
;
34 ULONG CsrMaxApiRequestThreads
;
35 ULONG CsrTotalPerProcessDataLength
;
37 HANDLE BNOLinksDirectory
;
38 HANDLE SessionObjectDirectory
;
39 HANDLE DosDevicesDirectory
;
40 SYSTEM_BASIC_INFORMATION CsrNtSysInfo
;
43 /* PRIVATE FUNCTIONS **********************************************************/
45 /* === INIT ROUTINES === */
48 * @name CsrSetProcessSecurity
50 * The CsrSetProcessSecurity routine protects access to the CSRSS process
51 * from unauthorized tampering.
55 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
62 CsrSetProcessSecurity(VOID
)
65 HANDLE hToken
, hProcess
= NtCurrentProcess();
67 PTOKEN_USER TokenInfo
= NULL
;
68 PSECURITY_DESCRIPTOR ProcSd
= NULL
;
73 Status
= NtOpenProcessToken(hProcess
, TOKEN_QUERY
, &hToken
);
74 if (!NT_SUCCESS(Status
)) goto Quickie
;
76 /* Get the Token User Length */
77 NtQueryInformationToken(hToken
, TokenUser
, NULL
, 0, &Length
);
79 /* Allocate space for it */
80 TokenInfo
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Length
);
83 Status
= STATUS_NO_MEMORY
;
87 /* Now query the data */
88 Status
= NtQueryInformationToken(hToken
, TokenUser
, TokenInfo
, Length
, &Length
);
90 if (!NT_SUCCESS(Status
)) goto Quickie
;
92 /* Now check the SID Length */
93 UserSid
= TokenInfo
->User
.Sid
;
94 Length
= RtlLengthSid(UserSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
96 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
97 ProcSd
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
100 Status
= STATUS_NO_MEMORY
;
104 /* Set the pointer to the DACL */
105 Dacl
= (PACL
)((ULONG_PTR
)ProcSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
107 /* Now create the SD itself */
108 Status
= RtlCreateSecurityDescriptor(ProcSd
, SECURITY_DESCRIPTOR_REVISION
);
109 if (!NT_SUCCESS(Status
))
111 DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status
);
115 /* Create the DACL for it*/
116 Status
= RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
117 if (!NT_SUCCESS(Status
))
119 DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status
);
124 Status
= RtlAddAccessAllowedAce(Dacl
,
126 PROCESS_VM_READ
| PROCESS_VM_WRITE
|
127 PROCESS_VM_OPERATION
| PROCESS_DUP_HANDLE
|
128 PROCESS_TERMINATE
| PROCESS_SUSPEND_RESUME
|
129 PROCESS_QUERY_INFORMATION
| READ_CONTROL
,
131 if (!NT_SUCCESS(Status
))
133 DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status
);
137 /* Clear the DACL in the SD */
138 Status
= RtlSetDaclSecurityDescriptor(ProcSd
, TRUE
, Dacl
, FALSE
);
139 if (!NT_SUCCESS(Status
))
141 DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status
);
145 /* Write the SD into the Process */
146 Status
= NtSetSecurityObject(hProcess
, DACL_SECURITY_INFORMATION
, ProcSd
);
147 if (!NT_SUCCESS(Status
))
149 DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status
);
153 /* Free the memory and return */
155 if (ProcSd
) RtlFreeHeap(CsrHeap
, 0, ProcSd
);
156 RtlFreeHeap(CsrHeap
, 0, TokenInfo
);
161 * @name CsrSetDirectorySecurity
163 * The CsrSetDirectorySecurity routine sets the security descriptor for the
164 * specified Object Directory.
166 * @param ObjectDirectory
167 * Handle fo the Object Directory to protect.
169 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
176 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory
)
178 /* FIXME: Implement */
179 return STATUS_SUCCESS
;
183 * @name GetDosDevicesProtection
185 * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
188 * @param DosDevicesSd
189 * Pointer to the Security Descriptor to return.
191 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
193 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
194 * regular users may or may not have full access to the directory.
199 GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd
)
201 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
202 SID_IDENTIFIER_AUTHORITY CreatorAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
203 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
204 PSID WorldSid
, CreatorSid
, AdminSid
, SystemSid
;
205 UCHAR KeyValueBuffer
[0x40];
206 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
207 UNICODE_STRING KeyName
;
208 ULONG ProtectionMode
= 0;
209 OBJECT_ATTRIBUTES ObjectAttributes
;
211 PACCESS_ALLOWED_ACE Ace
;
214 ULONG ResultLength
, SidLength
, AclLength
;
217 Status
= RtlCreateSecurityDescriptor(DosDevicesSd
, SECURITY_DESCRIPTOR_REVISION
);
218 ASSERT(NT_SUCCESS(Status
));
220 /* Initialize the System SID */
221 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
222 SECURITY_LOCAL_SYSTEM_RID
,
225 ASSERT(NT_SUCCESS(Status
));
227 /* Initialize the World SID */
228 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
, 1,
232 ASSERT(NT_SUCCESS(Status
));
234 /* Initialize the Admin SID */
235 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 2,
236 SECURITY_BUILTIN_DOMAIN_RID
,
237 DOMAIN_ALIAS_RID_ADMINS
,
240 ASSERT(NT_SUCCESS(Status
));
242 /* Initialize the Creator SID */
243 Status
= RtlAllocateAndInitializeSid(&CreatorAuthority
, 1,
244 SECURITY_CREATOR_OWNER_RID
,
247 ASSERT(NT_SUCCESS(Status
));
249 /* Open the Session Manager Key */
250 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
251 InitializeObjectAttributes(&ObjectAttributes
,
253 OBJ_CASE_INSENSITIVE
,
256 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
257 if (NT_SUCCESS(Status
))
259 /* Read the key value */
260 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
261 Status
= NtQueryValueKey(hKey
,
263 KeyValuePartialInformation
,
265 sizeof(KeyValueBuffer
),
268 /* Make sure it's what we expect it to be */
269 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
270 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
271 (*(PULONG
)KeyValuePartialInfo
->Data
))
273 /* Save the Protection Mode */
274 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
277 /* Close the handle */
281 /* Check the Protection Mode */
282 if (ProtectionMode
& 3)
284 /* Calculate SID Lengths */
285 SidLength
= RtlLengthSid(CreatorSid
) + RtlLengthSid(SystemSid
) +
286 RtlLengthSid(AdminSid
);
287 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
289 /* Allocate memory for the DACL */
290 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
291 ASSERT(Dacl
!= NULL
);
293 /* Build the ACL and add 3 ACEs */
294 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
295 ASSERT(NT_SUCCESS(Status
));
296 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
297 ASSERT(NT_SUCCESS(Status
));
298 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, AdminSid
);
299 ASSERT(NT_SUCCESS(Status
));
300 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, CreatorSid
);
301 ASSERT(NT_SUCCESS(Status
));
303 /* Edit the ACEs to make them inheritable */
304 Status
= RtlGetAce(Dacl
, 0, (PVOID
*)&Ace
);
305 ASSERT(NT_SUCCESS(Status
));
306 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
307 Status
= RtlGetAce(Dacl
, 1, (PVOID
*)&Ace
);
308 ASSERT(NT_SUCCESS(Status
));
309 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
310 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
311 ASSERT(NT_SUCCESS(Status
));
312 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
314 /* Set this DACL with the SD */
315 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
316 ASSERT(NT_SUCCESS(Status
));
321 /* Calculate SID Lengths */
322 SidLength
= RtlLengthSid(WorldSid
) + RtlLengthSid(SystemSid
);
323 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
325 /* Allocate memory for the DACL */
326 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
327 ASSERT(Dacl
!= NULL
);
329 /* Build the ACL and add 3 ACEs */
330 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
331 ASSERT(NT_SUCCESS(Status
));
332 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
, WorldSid
);
333 ASSERT(NT_SUCCESS(Status
));
334 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
335 ASSERT(NT_SUCCESS(Status
));
336 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, WorldSid
);
337 ASSERT(NT_SUCCESS(Status
));
339 /* Edit the last ACE to make it inheritable */
340 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
341 ASSERT(NT_SUCCESS(Status
));
342 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
344 /* Set this DACL with the SD */
345 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
346 ASSERT(NT_SUCCESS(Status
));
350 /* FIXME: failure cases! Fail: */
351 /* Free the memory */
352 RtlFreeHeap(CsrHeap
, 0, Dacl
);
354 /* FIXME: semi-failure cases! Quickie: */
357 RtlFreeSid(CreatorSid
);
358 RtlFreeSid(AdminSid
);
359 RtlFreeSid(WorldSid
);
360 RtlFreeSid(SystemSid
);
367 * @name FreeDosDevicesProtection
369 * The FreeDosDevicesProtection frees the security descriptor that was created
370 * by GetDosDevicesProtection
372 * @param DosDevicesSd
373 * Pointer to the security descriptor to free.
382 FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd
)
385 BOOLEAN Present
, Default
;
388 /* Get the DACL corresponding to this SD */
389 Status
= RtlGetDaclSecurityDescriptor(DosDevicesSd
, &Present
, &Dacl
, &Default
);
390 ASSERT(NT_SUCCESS(Status
));
392 ASSERT(Dacl
!= NULL
);
395 if ((NT_SUCCESS(Status
)) && (Dacl
)) RtlFreeHeap(CsrHeap
, 0, Dacl
);
399 * @name CsrCreateSessionObjectDirectory
401 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
402 * Session and Dos Devices directories for the specified session.
405 * Session ID for which to create the directories.
407 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
414 CsrCreateSessionObjectDirectory(IN ULONG Session
)
416 WCHAR SessionBuffer
[512], BnoBuffer
[512];
417 UNICODE_STRING SessionString
, BnoString
;
418 OBJECT_ATTRIBUTES ObjectAttributes
;
420 SECURITY_DESCRIPTOR DosDevicesSd
;
423 /* Generate the Session BNOLINKS Directory name */
424 swprintf(SessionBuffer
, L
"%ws\\BNOLINKS", SESSION_ROOT
);
425 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
428 InitializeObjectAttributes(&ObjectAttributes
,
430 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
433 Status
= NtCreateDirectoryObject(&BNOLinksDirectory
,
434 DIRECTORY_ALL_ACCESS
,
436 if (!NT_SUCCESS(Status
))
438 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
439 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
443 /* Now add the Session ID */
444 swprintf(SessionBuffer
, L
"%ld", Session
);
445 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
447 /* Check if this is the first Session */
450 /* Not the first, so the name will be slighly more complex */
451 swprintf(BnoBuffer
, L
"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT
, Session
);
452 RtlInitUnicodeString(&BnoString
, BnoBuffer
);
456 /* Use the direct name */
457 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
460 /* Create the symlink */
461 InitializeObjectAttributes(&ObjectAttributes
,
463 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
466 Status
= NtCreateSymbolicLinkObject(&BnoHandle
,
467 SYMBOLIC_LINK_ALL_ACCESS
,
470 if (!NT_SUCCESS(Status
))
472 DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
473 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
477 /* Create the \DosDevices Security Descriptor */
478 Status
= GetDosDevicesProtection(&DosDevicesSd
);
479 if (!NT_SUCCESS(Status
)) return Status
;
481 /* Now create a directory for this session */
482 swprintf(SessionBuffer
, L
"%ws\\%ld", SESSION_ROOT
, Session
);
483 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
485 /* Create the directory */
486 InitializeObjectAttributes(&ObjectAttributes
,
488 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
491 Status
= NtCreateDirectoryObject(&SessionObjectDirectory
,
492 DIRECTORY_ALL_ACCESS
,
494 if (!NT_SUCCESS(Status
))
496 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
497 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
498 FreeDosDevicesProtection(&DosDevicesSd
);
502 /* Next, create a directory for this session's DOS Devices */
503 RtlInitUnicodeString(&SessionString
, L
"DosDevices");
504 InitializeObjectAttributes(&ObjectAttributes
,
506 OBJ_CASE_INSENSITIVE
,
507 SessionObjectDirectory
,
509 Status
= NtCreateDirectoryObject(&DosDevicesDirectory
,
510 DIRECTORY_ALL_ACCESS
,
512 if (!NT_SUCCESS(Status
))
514 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
515 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
518 /* Release the Security Descriptor */
519 FreeDosDevicesProtection(&DosDevicesSd
);
526 * @name CsrParseServerCommandLine
528 * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
529 * registry and performs operations for each entry found.
531 * @param ArgumentCount
532 * Number of arguments on the command line.
535 * Array of arguments.
537 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
544 CsrParseServerCommandLine(IN ULONG ArgumentCount
,
545 IN PCHAR Arguments
[])
548 PCHAR ParameterName
= NULL
, ParameterValue
= NULL
, EntryPoint
, ServerString
;
550 ANSI_STRING AnsiString
;
551 OBJECT_ATTRIBUTES ObjectAttributes
;
553 /* Set the Defaults */
554 CsrTotalPerProcessDataLength
= 0;
555 CsrObjectDirectory
= NULL
;
556 CsrMaxApiRequestThreads
= 16;
558 /* Save our Session ID, and create a Directory for it */
559 SessionId
= NtCurrentPeb()->SessionId
;
560 Status
= CsrCreateSessionObjectDirectory(SessionId
);
561 if (!NT_SUCCESS(Status
))
563 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
566 /* It's not fatal if the session ID isn't zero */
567 if (SessionId
!= 0) return Status
;
568 ASSERT(NT_SUCCESS(Status
));
571 /* Loop through every argument */
572 for (i
= 1; i
< ArgumentCount
; i
++)
574 /* Split Name and Value */
575 ParameterName
= Arguments
[i
];
576 ParameterValue
= NULL
;
577 ParameterValue
= strchr(ParameterName
, '=');
578 if (ParameterValue
) *ParameterValue
++ = ANSI_NULL
;
579 DPRINT("Name=%s, Value=%s\n", ParameterName
, ParameterValue
);
581 /* Check for Object Directory */
582 if (_stricmp(ParameterName
, "ObjectDirectory") == 0)
584 /* Check if a session ID is specified */
587 DPRINT1("Sessions not yet implemented\n");
591 /* Initialize the directory name */
592 RtlInitAnsiString(&AnsiString
, ParameterValue
);
593 Status
= RtlAnsiStringToUnicodeString(&CsrDirectoryName
,
596 ASSERT(NT_SUCCESS(Status
) || SessionId
!= 0);
597 if (!NT_SUCCESS(Status
)) return Status
;
600 InitializeObjectAttributes(&ObjectAttributes
,
602 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
605 Status
= NtCreateDirectoryObject(&CsrObjectDirectory
,
606 DIRECTORY_ALL_ACCESS
,
608 if (!NT_SUCCESS(Status
)) return Status
;
611 Status
= CsrSetDirectorySecurity(CsrObjectDirectory
);
612 if (!NT_SUCCESS(Status
)) return Status
;
614 else if (_stricmp(ParameterName
, "SubSystemType") == 0)
618 else if (_stricmp(ParameterName
, "MaxRequestThreads") == 0)
620 Status
= RtlCharToInteger(ParameterValue
,
622 &CsrMaxApiRequestThreads
);
624 else if (_stricmp(ParameterName
, "RequestThreads") == 0)
627 Status
= STATUS_SUCCESS
;
629 else if (_stricmp(ParameterName
, "ProfileControl") == 0)
633 else if (_stricmp(ParameterName
, "SharedSection") == 0)
635 /* Create the Section */
636 Status
= CsrSrvCreateSharedSection(ParameterValue
);
637 if (!NT_SUCCESS(Status
))
639 DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
640 ParameterName
, ParameterValue
, Status
);
645 Status
= CsrLoadServerDll("CSRSS" /* "CSRSRV" */, NULL
, CSRSRV_SERVERDLL_INDEX
);
647 else if (_stricmp(ParameterName
, "ServerDll") == 0)
649 /* Loop the command line */
651 Status
= STATUS_INVALID_PARAMETER
;
652 ServerString
= ParameterValue
;
653 while (*ServerString
)
655 /* Check for the Entry Point */
656 if ((*ServerString
== ':') && (!EntryPoint
))
658 /* Found it. Add a nullchar and save it */
659 *ServerString
++ = ANSI_NULL
;
660 EntryPoint
= ServerString
;
663 /* Check for the Dll Index */
664 if (*ServerString
++ == ',') break;
667 /* Did we find something to load? */
670 DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
671 ParameterValue
, Status
);
675 /* Convert it to a ULONG */
676 Status
= RtlCharToInteger(ServerString
, 10, &DllIndex
);
678 /* Add a null char if it was valid */
679 if (NT_SUCCESS(Status
)) ServerString
[-1] = ANSI_NULL
;
682 if (CsrDebug
& 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue
, EntryPoint
);
683 Status
= CsrLoadServerDll(ParameterValue
, EntryPoint
, DllIndex
);
684 if (!NT_SUCCESS(Status
))
686 DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
687 ParameterValue
, Status
);
691 else if (_stricmp(ParameterName
, "Windows") == 0)
694 // Check whether we want to start in pure GUI or pure CLI.
698 /* Invalid parameter on the command line */
699 Status
= STATUS_INVALID_PARAMETER
;
708 * @name CsrInitCsrRootProcess
710 * The CsrInitCsrRootProcess routine further initializes the CSR Root Process
711 * created by CsrInitializeProcessStructure, by allocating and initializing
712 * per-process data for each Server DLL.
716 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
723 CsrInitCsrRootProcess(VOID
)
726 PCSR_SERVER_DLL ServerDll
;
729 /* All Server DLLs are now loaded, allocate a heap for the Root Process */
730 ProcessData
= RtlAllocateHeap(CsrHeap
,
732 CsrTotalPerProcessDataLength
);
735 DPRINT1("CSRSRV:%s: RtlAllocateHeap failed (Status=%08lx)\n",
736 __FUNCTION__
, STATUS_NO_MEMORY
);
737 return STATUS_NO_MEMORY
;
741 * Our Root Process was never officially initialized,
742 * so write the data for each Server DLL manually.
746 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
748 /* Get the current Server */
749 ServerDll
= CsrLoadedServerDll
[i
];
751 /* Is it loaded, and does it have per process data? */
752 if (ServerDll
&& ServerDll
->SizeOfProcessData
)
754 /* It does, give it part of our allocated heap */
755 CsrRootProcess
->ServerData
[i
] = ProcessData
;
757 /* Move to the next heap position */
758 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
759 ServerDll
->SizeOfProcessData
);
763 /* Nothing for this Server DLL */
764 CsrRootProcess
->ServerData
[i
] = NULL
;
768 /* Now initialize the Root Process manually as well */
769 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
771 /* Get the current Server */
772 ServerDll
= CsrLoadedServerDll
[i
];
774 /* Is it loaded, and does it a callback for new processes? */
775 if (ServerDll
&& ServerDll
->NewProcessCallback
)
777 /* Call the callback */
778 ServerDll
->NewProcessCallback(NULL
, CsrRootProcess
);
782 return STATUS_SUCCESS
;
786 * @name CsrCreateLocalSystemSD
788 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
789 * the local account with PORT_ALL_ACCESS.
791 * @param LocalSystemSd
792 * Pointer to a pointer to the security descriptor to create.
794 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
801 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR
*LocalSystemSd
)
803 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
806 PSECURITY_DESCRIPTOR SystemSd
;
810 /* Initialize the System SID */
811 RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
812 SECURITY_LOCAL_SYSTEM_RID
,
816 /* Get the length of the SID */
817 Length
= RtlLengthSid(SystemSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
819 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
820 SystemSd
= RtlAllocateHeap(CsrHeap
, 0, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
822 /* Set the pointer to the DACL */
823 Dacl
= (PACL
)((ULONG_PTR
)SystemSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
825 /* Now create the SD itself */
826 Status
= RtlCreateSecurityDescriptor(SystemSd
, SECURITY_DESCRIPTOR_REVISION
);
827 if (!NT_SUCCESS(Status
)) goto Quit
;
829 /* Create the DACL for it */
830 RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
833 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, PORT_ALL_ACCESS
, SystemSid
);
834 if (!NT_SUCCESS(Status
)) goto Quit
;
836 /* Clear the DACL in the SD */
837 Status
= RtlSetDaclSecurityDescriptor(SystemSd
, TRUE
, Dacl
, FALSE
);
838 if (!NT_SUCCESS(Status
)) goto Quit
;
841 if (!NT_SUCCESS(Status
))
843 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
847 /* Free the SID and return*/
848 RtlFreeSid(SystemSid
);
849 *LocalSystemSd
= SystemSd
;
854 * @name CsrSbApiPortInitialize
856 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
857 * communications with the Session Manager (SM) and initializes the static
858 * thread that will handle connection requests and APIs.
862 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
869 CsrSbApiPortInitialize(VOID
)
872 PSECURITY_DESCRIPTOR PortSd
;
873 OBJECT_ATTRIBUTES ObjectAttributes
;
875 HANDLE hRequestThread
;
878 /* Calculate how much space we'll need for the Port Name */
879 Size
= CsrDirectoryName
.Length
+ sizeof(SB_PORT_NAME
) + sizeof(WCHAR
);
881 /* Create the buffer for it */
882 CsrSbApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
883 if (!CsrSbApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
885 /* Setup the rest of the empty string */
886 CsrSbApiPortName
.Length
= 0;
887 CsrSbApiPortName
.MaximumLength
= (USHORT
)Size
;
889 /* Now append the full port name */
890 RtlAppendUnicodeStringToString(&CsrSbApiPortName
, &CsrDirectoryName
);
891 RtlAppendUnicodeToString(&CsrSbApiPortName
, UNICODE_PATH_SEP
);
892 RtlAppendUnicodeToString(&CsrSbApiPortName
, SB_PORT_NAME
);
893 if (CsrDebug
& 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName
);
895 /* Create Security Descriptor for this Port */
896 Status
= CsrCreateLocalSystemSD(&PortSd
);
897 if (!NT_SUCCESS(Status
)) return Status
;
899 /* Initialize the Attributes */
900 InitializeObjectAttributes(&ObjectAttributes
,
906 /* Create the Port Object */
907 Status
= NtCreatePort(&CsrSbApiPort
,
909 sizeof(SB_CONNECTION_INFO
),
911 32 * sizeof(SB_API_MSG
));
912 if (PortSd
) RtlFreeHeap(CsrHeap
, 0, PortSd
);
914 if (NT_SUCCESS(Status
))
916 /* Create the Thread to handle the API Requests */
917 Status
= RtlCreateUserThread(NtCurrentProcess(),
923 (PVOID
)CsrSbApiRequestThread
,
927 if (NT_SUCCESS(Status
))
929 /* Add it as a Static Server Thread */
930 CsrSbApiRequestThreadPtr
= CsrAddStaticServerThread(hRequestThread
,
935 Status
= NtResumeThread(hRequestThread
, NULL
);
943 /* PUBLIC FUNCTIONS ***********************************************************/
946 * @name CsrServerInitialization
949 * The CsrServerInitialization routine is the native (not Server) entrypoint
950 * of this Server DLL. It serves as the entrypoint for CSRSS.
952 * @param ArgumentCount
953 * Number of arguments on the command line.
956 * Array of arguments from the command line.
958 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
965 CsrServerInitialization(IN ULONG ArgumentCount
,
966 IN PCHAR Arguments
[])
968 NTSTATUS Status
= STATUS_SUCCESS
;
970 /* Cache System Basic Information so we don't always request it */
971 Status
= NtQuerySystemInformation(SystemBasicInformation
,
973 sizeof(SYSTEM_BASIC_INFORMATION
),
975 if (!NT_SUCCESS(Status
))
977 DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=0x%08lx)\n",
978 __FUNCTION__
, Status
);
983 CsrHeap
= RtlGetProcessHeap();
985 /* Set our Security Descriptor to protect the process */
986 Status
= CsrSetProcessSecurity();
987 if (!NT_SUCCESS(Status
))
989 DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=0x%08lx)\n",
990 __FUNCTION__
, Status
);
994 /* Set up Session Support */
995 Status
= CsrInitializeNtSessionList();
996 if (!NT_SUCCESS(Status
))
998 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=0x%08lx)\n",
999 __FUNCTION__
, Status
);
1003 /* Set up Process Support and allocate the CSR Root Process */
1004 Status
= CsrInitializeProcessStructure();
1005 if (!NT_SUCCESS(Status
))
1007 DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=0x%08lx)\n",
1008 __FUNCTION__
, Status
);
1012 /* Parse the command line */
1013 Status
= CsrParseServerCommandLine(ArgumentCount
, Arguments
);
1014 if (!NT_SUCCESS(Status
))
1016 DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=0x%08lx)\n",
1017 __FUNCTION__
, Status
);
1021 /* Finish to initialize the CSR Root Process */
1022 Status
= CsrInitCsrRootProcess();
1023 if (!NT_SUCCESS(Status
))
1025 DPRINT1("CSRSRV:%s: CsrInitCsrRootProcess failed (Status=0x%08lx)\n",
1026 __FUNCTION__
, Status
);
1030 /* Now initialize our API Port */
1031 Status
= CsrApiPortInitialize();
1032 if (!NT_SUCCESS(Status
))
1034 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=0x%08lx)\n",
1035 __FUNCTION__
, Status
);
1039 /* Initialize the API Port for SM communication */
1040 Status
= CsrSbApiPortInitialize();
1041 if (!NT_SUCCESS(Status
))
1043 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=0x%08lx)\n",
1044 __FUNCTION__
, Status
);
1048 /* We're all set! Connect to SM! */
1049 Status
= SmConnectToSm(&CsrSbApiPortName
,
1051 IMAGE_SUBSYSTEM_WINDOWS_GUI
,
1053 if (!NT_SUCCESS(Status
))
1055 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=0x%08lx)\n",
1056 __FUNCTION__
, Status
);
1060 /* Have us handle Hard Errors */
1061 Status
= NtSetDefaultHardErrorPort(CsrApiPort
);
1062 if (!NT_SUCCESS(Status
))
1064 DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=0x%08lx)\n",
1065 __FUNCTION__
, Status
);
1074 * @name CsrPopulateDosDevices
1075 * @unimplemented NT5.1
1077 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1078 * to populate the Dos Devices Object Directory for the session.
1089 CsrPopulateDosDevices(VOID
)
1091 DPRINT1("Deprecated API in r55585.\n");
1097 DllMain(IN HINSTANCE hInstanceDll
,
1099 IN LPVOID lpReserved
)
1101 /* We don't do much */
1102 UNREFERENCED_PARAMETER(hInstanceDll
);
1103 UNREFERENCED_PARAMETER(dwReason
);
1104 UNREFERENCED_PARAMETER(lpReserved
);