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 SYSTEM_BASIC_INFORMATION CsrNtSysInfo
;
38 /* PRIVATE FUNCTIONS **********************************************************/
40 /* === INIT ROUTINES === */
43 * @name CsrSetProcessSecurity
45 * The CsrSetProcessSecurity routine protects access to the CSRSS process
46 * from unauthorized tampering.
50 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
57 CsrSetProcessSecurity(VOID
)
60 HANDLE hToken
, hProcess
= NtCurrentProcess();
62 PTOKEN_USER TokenInfo
= NULL
;
63 PSECURITY_DESCRIPTOR ProcSd
= NULL
;
68 Status
= NtOpenProcessToken(hProcess
, TOKEN_QUERY
, &hToken
);
69 if (!NT_SUCCESS(Status
)) goto Quickie
;
71 /* Get the Token User Length */
72 NtQueryInformationToken(hToken
, TokenUser
, NULL
, 0, &Length
);
74 /* Allocate space for it */
75 TokenInfo
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Length
);
78 Status
= STATUS_NO_MEMORY
;
82 /* Now query the data */
83 Status
= NtQueryInformationToken(hToken
, TokenUser
, TokenInfo
, Length
, &Length
);
85 if (!NT_SUCCESS(Status
)) goto Quickie
;
87 /* Now check the SID Length */
88 UserSid
= TokenInfo
->User
.Sid
;
89 Length
= RtlLengthSid(UserSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
91 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
92 ProcSd
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
95 Status
= STATUS_NO_MEMORY
;
99 /* Set the pointer to the DACL */
100 Dacl
= (PACL
)((ULONG_PTR
)ProcSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
102 /* Now create the SD itself */
103 Status
= RtlCreateSecurityDescriptor(ProcSd
, SECURITY_DESCRIPTOR_REVISION
);
104 if (!NT_SUCCESS(Status
))
106 DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status
);
110 /* Create the DACL for it*/
111 Status
= RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
112 if (!NT_SUCCESS(Status
))
114 DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status
);
119 Status
= RtlAddAccessAllowedAce(Dacl
,
121 PROCESS_VM_READ
| PROCESS_VM_WRITE
|
122 PROCESS_VM_OPERATION
| PROCESS_DUP_HANDLE
|
123 PROCESS_TERMINATE
| PROCESS_SUSPEND_RESUME
|
124 PROCESS_QUERY_INFORMATION
| READ_CONTROL
,
126 if (!NT_SUCCESS(Status
))
128 DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status
);
132 /* Clear the DACL in the SD */
133 Status
= RtlSetDaclSecurityDescriptor(ProcSd
, TRUE
, Dacl
, FALSE
);
134 if (!NT_SUCCESS(Status
))
136 DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status
);
140 /* Write the SD into the Process */
141 Status
= NtSetSecurityObject(hProcess
, DACL_SECURITY_INFORMATION
, ProcSd
);
142 if (!NT_SUCCESS(Status
))
144 DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status
);
148 /* Free the memory and return */
150 if (ProcSd
) RtlFreeHeap(CsrHeap
, 0, ProcSd
);
151 RtlFreeHeap(CsrHeap
, 0, TokenInfo
);
156 * @name CsrSetDirectorySecurity
158 * The CsrSetDirectorySecurity routine sets the security descriptor for the
159 * specified Object Directory.
161 * @param ObjectDirectory
162 * Handle fo the Object Directory to protect.
164 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
171 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory
)
173 /* FIXME: Implement */
174 return STATUS_SUCCESS
;
178 * @name GetDosDevicesProtection
180 * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
183 * @param DosDevicesSd
184 * Pointer to the Security Descriptor to return.
186 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
188 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
189 * regular users may or may not have full access to the directory.
194 GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd
)
196 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
197 SID_IDENTIFIER_AUTHORITY CreatorAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
198 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
199 PSID WorldSid
, CreatorSid
, AdminSid
, SystemSid
;
200 UCHAR KeyValueBuffer
[0x40];
201 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
202 UNICODE_STRING KeyName
;
203 ULONG ProtectionMode
= 0;
204 OBJECT_ATTRIBUTES ObjectAttributes
;
206 PACCESS_ALLOWED_ACE Ace
;
209 ULONG ResultLength
, SidLength
, AclLength
;
212 Status
= RtlCreateSecurityDescriptor(DosDevicesSd
, SECURITY_DESCRIPTOR_REVISION
);
213 ASSERT(NT_SUCCESS(Status
));
215 /* Initialize the System SID */
216 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
217 SECURITY_LOCAL_SYSTEM_RID
,
220 ASSERT(NT_SUCCESS(Status
));
222 /* Initialize the World SID */
223 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
, 1,
227 ASSERT(NT_SUCCESS(Status
));
229 /* Initialize the Admin SID */
230 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 2,
231 SECURITY_BUILTIN_DOMAIN_RID
,
232 DOMAIN_ALIAS_RID_ADMINS
,
235 ASSERT(NT_SUCCESS(Status
));
237 /* Initialize the Creator SID */
238 Status
= RtlAllocateAndInitializeSid(&CreatorAuthority
, 1,
239 SECURITY_CREATOR_OWNER_RID
,
242 ASSERT(NT_SUCCESS(Status
));
244 /* Open the Session Manager Key */
245 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
246 InitializeObjectAttributes(&ObjectAttributes
,
248 OBJ_CASE_INSENSITIVE
,
251 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
252 if (NT_SUCCESS(Status
))
254 /* Read the key value */
255 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
256 Status
= NtQueryValueKey(hKey
,
258 KeyValuePartialInformation
,
260 sizeof(KeyValueBuffer
),
263 /* Make sure it's what we expect it to be */
264 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
265 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
266 (*(PULONG
)KeyValuePartialInfo
->Data
))
268 /* Save the Protection Mode */
269 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
272 /* Close the handle */
276 /* Check the Protection Mode */
277 if (ProtectionMode
& 3)
279 /* Calculate SID Lengths */
280 SidLength
= RtlLengthSid(CreatorSid
) + RtlLengthSid(SystemSid
) +
281 RtlLengthSid(AdminSid
);
282 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
284 /* Allocate memory for the DACL */
285 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
286 ASSERT(Dacl
!= NULL
);
288 /* Build the ACL and add 3 ACEs */
289 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
290 ASSERT(NT_SUCCESS(Status
));
291 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
292 ASSERT(NT_SUCCESS(Status
));
293 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, AdminSid
);
294 ASSERT(NT_SUCCESS(Status
));
295 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, CreatorSid
);
296 ASSERT(NT_SUCCESS(Status
));
298 /* Edit the ACEs to make them inheritable */
299 Status
= RtlGetAce(Dacl
, 0, (PVOID
*)&Ace
);
300 ASSERT(NT_SUCCESS(Status
));
301 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
302 Status
= RtlGetAce(Dacl
, 1, (PVOID
*)&Ace
);
303 ASSERT(NT_SUCCESS(Status
));
304 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
305 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
306 ASSERT(NT_SUCCESS(Status
));
307 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
309 /* Set this DACL with the SD */
310 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
311 ASSERT(NT_SUCCESS(Status
));
316 /* Calculate SID Lengths */
317 SidLength
= RtlLengthSid(WorldSid
) + RtlLengthSid(SystemSid
);
318 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
320 /* Allocate memory for the DACL */
321 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
322 ASSERT(Dacl
!= NULL
);
324 /* Build the ACL and add 3 ACEs */
325 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
326 ASSERT(NT_SUCCESS(Status
));
327 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
, WorldSid
);
328 ASSERT(NT_SUCCESS(Status
));
329 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
330 ASSERT(NT_SUCCESS(Status
));
331 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, WorldSid
);
332 ASSERT(NT_SUCCESS(Status
));
334 /* Edit the last ACE to make it inheritable */
335 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
336 ASSERT(NT_SUCCESS(Status
));
337 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
339 /* Set this DACL with the SD */
340 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
341 ASSERT(NT_SUCCESS(Status
));
345 /* FIXME: failure cases! Fail: */
346 /* Free the memory */
347 RtlFreeHeap(CsrHeap
, 0, Dacl
);
349 /* FIXME: semi-failure cases! Quickie: */
352 RtlFreeSid(CreatorSid
);
353 RtlFreeSid(AdminSid
);
354 RtlFreeSid(WorldSid
);
355 RtlFreeSid(SystemSid
);
362 * @name FreeDosDevicesProtection
364 * The FreeDosDevicesProtection frees the security descriptor that was created
365 * by GetDosDevicesProtection
367 * @param DosDevicesSd
368 * Pointer to the security descriptor to free.
377 FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd
)
380 BOOLEAN Present
, Default
;
383 /* Get the DACL corresponding to this SD */
384 Status
= RtlGetDaclSecurityDescriptor(DosDevicesSd
, &Present
, &Dacl
, &Default
);
385 ASSERT(NT_SUCCESS(Status
));
387 ASSERT(Dacl
!= NULL
);
390 if ((NT_SUCCESS(Status
)) && (Dacl
)) RtlFreeHeap(CsrHeap
, 0, Dacl
);
394 * @name CsrCreateSessionObjectDirectory
396 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
397 * Session and Dos Devices directories for the specified session.
400 * Session ID for which to create the directories.
402 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
409 CsrCreateSessionObjectDirectory(IN ULONG Session
)
411 WCHAR SessionBuffer
[512], BnoBuffer
[512];
412 UNICODE_STRING SessionString
, BnoString
;
413 OBJECT_ATTRIBUTES ObjectAttributes
;
415 SECURITY_DESCRIPTOR DosDevicesSd
;
418 /* Generate the Session BNOLINKS Directory name */
419 swprintf(SessionBuffer
, L
"%ws\\BNOLINKS", SESSION_ROOT
);
420 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
423 InitializeObjectAttributes(&ObjectAttributes
,
425 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
428 Status
= NtCreateDirectoryObject(&BNOLinksDirectory
,
429 DIRECTORY_ALL_ACCESS
,
431 if (!NT_SUCCESS(Status
))
433 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
434 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
438 /* Now add the Session ID */
439 swprintf(SessionBuffer
, L
"%ld", Session
);
440 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
442 /* Check if this is the first Session */
445 /* Not the first, so the name will be slighly more complex */
446 swprintf(BnoBuffer
, L
"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT
, Session
);
447 RtlInitUnicodeString(&BnoString
, BnoBuffer
);
451 /* Use the direct name */
452 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
455 /* Create the symlink */
456 InitializeObjectAttributes(&ObjectAttributes
,
458 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
461 Status
= NtCreateSymbolicLinkObject(&BnoHandle
,
462 SYMBOLIC_LINK_ALL_ACCESS
,
465 if (!NT_SUCCESS(Status
))
467 DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
468 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
472 /* Create the \DosDevices Security Descriptor */
473 Status
= GetDosDevicesProtection(&DosDevicesSd
);
474 if (!NT_SUCCESS(Status
)) return Status
;
476 /* Now create a directory for this session */
477 swprintf(SessionBuffer
, L
"%ws\\%ld", SESSION_ROOT
, Session
);
478 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
480 /* Create the directory */
481 InitializeObjectAttributes(&ObjectAttributes
,
483 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
486 Status
= NtCreateDirectoryObject(&SessionObjectDirectory
,
487 DIRECTORY_ALL_ACCESS
,
489 if (!NT_SUCCESS(Status
))
491 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
492 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
493 FreeDosDevicesProtection(&DosDevicesSd
);
497 /* Next, create a directory for this session's DOS Devices */
498 RtlInitUnicodeString(&SessionString
, L
"DosDevices");
499 InitializeObjectAttributes(&ObjectAttributes
,
501 OBJ_CASE_INSENSITIVE
,
502 SessionObjectDirectory
,
504 Status
= NtCreateDirectoryObject(&DosDevicesDirectory
,
505 DIRECTORY_ALL_ACCESS
,
507 if (!NT_SUCCESS(Status
))
509 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
510 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
513 /* Release the Security Descriptor */
514 FreeDosDevicesProtection(&DosDevicesSd
);
521 * @name CsrParseServerCommandLine
523 * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
524 * registry and performs operations for each entry found.
526 * @param ArgumentCount
527 * Number of arguments on the command line.
530 * Array of arguments.
532 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
539 CsrParseServerCommandLine(IN ULONG ArgumentCount
,
540 IN PCHAR Arguments
[])
543 PCHAR ParameterName
= NULL
, ParameterValue
= NULL
, EntryPoint
, ServerString
;
545 ANSI_STRING AnsiString
;
546 OBJECT_ATTRIBUTES ObjectAttributes
;
548 /* Set the Defaults */
549 CsrTotalPerProcessDataLength
= 0;
550 CsrObjectDirectory
= NULL
;
551 CsrMaxApiRequestThreads
= 16;
553 /* Save our Session ID, and create a Directory for it */
554 SessionId
= NtCurrentPeb()->SessionId
;
555 Status
= CsrCreateSessionObjectDirectory(SessionId
);
556 if (!NT_SUCCESS(Status
))
558 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
561 /* It's not fatal if the session ID isn't zero */
562 if (SessionId
!= 0) return Status
;
563 ASSERT(NT_SUCCESS(Status
));
566 /* Loop through every argument */
567 for (i
= 1; i
< ArgumentCount
; i
++)
569 /* Split Name and Value */
570 ParameterName
= Arguments
[i
];
571 ParameterValue
= NULL
;
572 ParameterValue
= strchr(ParameterName
, '=');
573 if (ParameterValue
) *ParameterValue
++ = ANSI_NULL
;
574 DPRINT1("Name=%s, Value=%s\n", ParameterName
, ParameterValue
);
576 /* Check for Object Directory */
577 if (_stricmp(ParameterName
, "ObjectDirectory") == 0)
579 /* Check if a session ID is specified */
582 DPRINT1("Sessions not yet implemented\n");
586 /* Initialize the directory name */
587 RtlInitAnsiString(&AnsiString
, ParameterValue
);
588 Status
= RtlAnsiStringToUnicodeString(&CsrDirectoryName
,
591 ASSERT(NT_SUCCESS(Status
) || SessionId
!= 0);
592 if (!NT_SUCCESS(Status
)) return Status
;
595 InitializeObjectAttributes(&ObjectAttributes
,
597 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
600 Status
= NtCreateDirectoryObject(&CsrObjectDirectory
,
601 DIRECTORY_ALL_ACCESS
,
603 if (!NT_SUCCESS(Status
)) return Status
;
606 Status
= CsrSetDirectorySecurity(CsrObjectDirectory
);
607 if (!NT_SUCCESS(Status
)) return Status
;
609 else if (_stricmp(ParameterName
, "SubSystemType") == 0)
613 else if (_stricmp(ParameterName
, "MaxRequestThreads") == 0)
615 Status
= RtlCharToInteger(ParameterValue
,
617 &CsrMaxApiRequestThreads
);
619 else if (_stricmp(ParameterName
, "RequestThreads") == 0)
622 Status
= STATUS_SUCCESS
;
624 else if (_stricmp(ParameterName
, "ProfileControl") == 0)
628 else if (_stricmp(ParameterName
, "SharedSection") == 0)
630 /* Create the Section */
631 Status
= CsrSrvCreateSharedSection(ParameterValue
);
632 if (!NT_SUCCESS(Status
))
634 DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
635 ParameterName
, ParameterValue
, Status
);
640 Status
= CsrLoadServerDll("CSRSS" /* "CSRSRV" */, NULL
, CSRSRV_SERVERDLL_INDEX
);
642 else if (_stricmp(ParameterName
, "ServerDll") == 0)
644 /* Loop the command line */
646 Status
= STATUS_INVALID_PARAMETER
;
647 ServerString
= ParameterValue
;
648 while (*ServerString
)
650 /* Check for the Entry Point */
651 if ((*ServerString
== ':') && (!EntryPoint
))
653 /* Found it. Add a nullchar and save it */
654 *ServerString
++ = ANSI_NULL
;
655 EntryPoint
= ServerString
;
658 /* Check for the Dll Index */
659 if (*ServerString
++ == ',') break;
662 /* Did we find something to load? */
665 DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
666 ParameterValue
, Status
);
670 /* Convert it to a ULONG */
671 Status
= RtlCharToInteger(ServerString
, 10, &DllIndex
);
673 /* Add a null char if it was valid */
674 if (NT_SUCCESS(Status
)) ServerString
[-1] = ANSI_NULL
;
677 if (CsrDebug
& 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue
, EntryPoint
);
678 Status
= CsrLoadServerDll(ParameterValue
, EntryPoint
, DllIndex
);
679 if (!NT_SUCCESS(Status
))
681 DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
682 ParameterValue
, Status
);
686 else if (_stricmp(ParameterName
, "Windows") == 0)
689 // Check whether we want to start in pure GUI or pure CLI.
693 /* Invalid parameter on the command line */
694 Status
= STATUS_INVALID_PARAMETER
;
703 * @name CsrInitCsrRootProcess
705 * The CsrInitCsrRootProcess routine further initializes the CSR Root Process
706 * created by CsrInitializeProcessStructure, by allocating and initializing
707 * per-process data for each Server DLL.
711 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
718 CsrInitCsrRootProcess(VOID
)
721 PCSR_SERVER_DLL ServerDll
;
724 /* All Server DLLs are now loaded, allocate a heap for the Root Process */
725 ProcessData
= RtlAllocateHeap(CsrHeap
,
727 CsrTotalPerProcessDataLength
);
730 DPRINT1("CSRSRV:%s: RtlAllocateHeap failed (Status=%08lx)\n",
731 __FUNCTION__
, STATUS_NO_MEMORY
);
732 return STATUS_NO_MEMORY
;
736 * Our Root Process was never officially initialized,
737 * so write the data for each Server DLL manually.
741 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
743 /* Get the current Server */
744 ServerDll
= CsrLoadedServerDll
[i
];
746 /* Is it loaded, and does it have per process data? */
747 if (ServerDll
&& ServerDll
->SizeOfProcessData
)
749 /* It does, give it part of our allocated heap */
750 CsrRootProcess
->ServerData
[i
] = ProcessData
;
752 /* Move to the next heap position */
753 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
754 ServerDll
->SizeOfProcessData
);
758 /* Nothing for this Server DLL */
759 CsrRootProcess
->ServerData
[i
] = NULL
;
763 /* Now initialize the Root Process manually as well */
764 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
766 /* Get the current Server */
767 ServerDll
= CsrLoadedServerDll
[i
];
769 /* Is it loaded, and does it a callback for new processes? */
770 if (ServerDll
&& ServerDll
->NewProcessCallback
)
772 /* Call the callback */
773 ServerDll
->NewProcessCallback(NULL
, CsrRootProcess
);
777 return STATUS_SUCCESS
;
781 * @name CsrCreateLocalSystemSD
783 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
784 * the local account with PORT_ALL_ACCESS.
786 * @param LocalSystemSd
787 * Pointer to a pointer to the security descriptor to create.
789 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
796 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR
*LocalSystemSd
)
798 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
801 PSECURITY_DESCRIPTOR SystemSd
;
805 /* Initialize the System SID */
806 RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
807 SECURITY_LOCAL_SYSTEM_RID
,
811 /* Get the length of the SID */
812 Length
= RtlLengthSid(SystemSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
814 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
815 SystemSd
= RtlAllocateHeap(CsrHeap
, 0, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
817 /* Set the pointer to the DACL */
818 Dacl
= (PACL
)((ULONG_PTR
)SystemSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
820 /* Now create the SD itself */
821 Status
= RtlCreateSecurityDescriptor(SystemSd
, SECURITY_DESCRIPTOR_REVISION
);
822 if (!NT_SUCCESS(Status
)) goto Quit
;
824 /* Create the DACL for it */
825 RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
828 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, PORT_ALL_ACCESS
, SystemSid
);
829 if (!NT_SUCCESS(Status
)) goto Quit
;
831 /* Clear the DACL in the SD */
832 Status
= RtlSetDaclSecurityDescriptor(SystemSd
, TRUE
, Dacl
, FALSE
);
833 if (!NT_SUCCESS(Status
)) goto Quit
;
836 if (!NT_SUCCESS(Status
))
838 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
842 /* Free the SID and return*/
843 RtlFreeSid(SystemSid
);
844 *LocalSystemSd
= SystemSd
;
849 * @name CsrSbApiPortInitialize
851 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
852 * communications with the Session Manager (SM) and initializes the static
853 * thread that will handle connection requests and APIs.
857 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
864 CsrSbApiPortInitialize(VOID
)
867 PSECURITY_DESCRIPTOR PortSd
;
868 OBJECT_ATTRIBUTES ObjectAttributes
;
870 HANDLE hRequestThread
;
873 /* Calculate how much space we'll need for the Port Name */
874 Size
= CsrDirectoryName
.Length
+ sizeof(SB_PORT_NAME
) + sizeof(WCHAR
);
876 /* Create the buffer for it */
877 CsrSbApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
878 if (!CsrSbApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
880 /* Setup the rest of the empty string */
881 CsrSbApiPortName
.Length
= 0;
882 CsrSbApiPortName
.MaximumLength
= (USHORT
)Size
;
884 /* Now append the full port name */
885 RtlAppendUnicodeStringToString(&CsrSbApiPortName
, &CsrDirectoryName
);
886 RtlAppendUnicodeToString(&CsrSbApiPortName
, UNICODE_PATH_SEP
);
887 RtlAppendUnicodeToString(&CsrSbApiPortName
, SB_PORT_NAME
);
888 if (CsrDebug
& 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName
);
890 /* Create Security Descriptor for this Port */
891 Status
= CsrCreateLocalSystemSD(&PortSd
);
892 if (!NT_SUCCESS(Status
)) return Status
;
894 /* Initialize the Attributes */
895 InitializeObjectAttributes(&ObjectAttributes
,
901 /* Create the Port Object */
902 Status
= NtCreatePort(&CsrSbApiPort
,
904 sizeof(SB_CONNECTION_INFO
),
906 32 * sizeof(SB_API_MSG
));
907 if (PortSd
) RtlFreeHeap(CsrHeap
, 0, PortSd
);
909 if (NT_SUCCESS(Status
))
911 /* Create the Thread to handle the API Requests */
912 Status
= RtlCreateUserThread(NtCurrentProcess(),
918 (PVOID
)CsrSbApiRequestThread
,
922 if (NT_SUCCESS(Status
))
924 /* Add it as a Static Server Thread */
925 CsrSbApiRequestThreadPtr
= CsrAddStaticServerThread(hRequestThread
,
930 Status
= NtResumeThread(hRequestThread
, NULL
);
938 /* PUBLIC FUNCTIONS ***********************************************************/
941 * @name CsrServerInitialization
944 * The CsrServerInitialization routine is the native (not Server) entrypoint
945 * of this Server DLL. It serves as the entrypoint for CSRSS.
947 * @param ArgumentCount
948 * Number of arguments on the command line.
951 * Array of arguments from the command line.
953 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
960 CsrServerInitialization(IN ULONG ArgumentCount
,
961 IN PCHAR Arguments
[])
963 NTSTATUS Status
= STATUS_SUCCESS
;
965 /* Cache System Basic Information so we don't always request it */
966 Status
= NtQuerySystemInformation(SystemBasicInformation
,
968 sizeof(SYSTEM_BASIC_INFORMATION
),
970 if (!NT_SUCCESS(Status
))
972 DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=0x%08lx)\n",
973 __FUNCTION__
, Status
);
978 CsrHeap
= RtlGetProcessHeap();
980 /* Set our Security Descriptor to protect the process */
981 Status
= CsrSetProcessSecurity();
982 if (!NT_SUCCESS(Status
))
984 DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=0x%08lx)\n",
985 __FUNCTION__
, Status
);
989 /* Set up Session Support */
990 Status
= CsrInitializeNtSessionList();
991 if (!NT_SUCCESS(Status
))
993 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=0x%08lx)\n",
994 __FUNCTION__
, Status
);
998 /* Set up Process Support and allocate the CSR Root Process */
999 Status
= CsrInitializeProcessStructure();
1000 if (!NT_SUCCESS(Status
))
1002 DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=0x%08lx)\n",
1003 __FUNCTION__
, Status
);
1007 /* Parse the command line */
1008 Status
= CsrParseServerCommandLine(ArgumentCount
, Arguments
);
1009 if (!NT_SUCCESS(Status
))
1011 DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=0x%08lx)\n",
1012 __FUNCTION__
, Status
);
1016 /* Finish to initialize the CSR Root Process */
1017 Status
= CsrInitCsrRootProcess();
1018 if (!NT_SUCCESS(Status
))
1020 DPRINT1("CSRSRV:%s: CsrInitCsrRootProcess failed (Status=0x%08lx)\n",
1021 __FUNCTION__
, Status
);
1025 /* Now initialize our API Port */
1026 Status
= CsrApiPortInitialize();
1027 if (!NT_SUCCESS(Status
))
1029 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=0x%08lx)\n",
1030 __FUNCTION__
, Status
);
1034 /* Initialize the API Port for SM communication */
1035 Status
= CsrSbApiPortInitialize();
1036 if (!NT_SUCCESS(Status
))
1038 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=0x%08lx)\n",
1039 __FUNCTION__
, Status
);
1043 /* We're all set! Connect to SM! */
1044 Status
= SmConnectToSm(&CsrSbApiPortName
,
1046 IMAGE_SUBSYSTEM_WINDOWS_GUI
,
1048 if (!NT_SUCCESS(Status
))
1050 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=0x%08lx)\n",
1051 __FUNCTION__
, Status
);
1055 /* Have us handle Hard Errors */
1056 Status
= NtSetDefaultHardErrorPort(CsrApiPort
);
1057 if (!NT_SUCCESS(Status
))
1059 DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=0x%08lx)\n",
1060 __FUNCTION__
, Status
);
1069 * @name CsrPopulateDosDevices
1070 * @unimplemented NT5.1
1072 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1073 * to populate the Dos Devices Object Directory for the session.
1084 CsrPopulateDosDevices(VOID
)
1086 DPRINT1("Deprecated API in r55585.\n");
1092 DllMain(IN HINSTANCE hInstanceDll
,
1094 IN LPVOID lpReserved
)
1096 /* We don't do much */
1097 UNREFERENCED_PARAMETER(hInstanceDll
);
1098 UNREFERENCED_PARAMETER(dwReason
);
1099 UNREFERENCED_PARAMETER(lpReserved
);