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 **********************************************************/
42 CallHardError(IN PCSR_THREAD ThreadData
,
43 IN PHARDERROR_MSG HardErrorMessage
)
46 PCSR_SERVER_DLL ServerDll
;
48 DPRINT("CSR: %s called\n", __FUNCTION__
);
50 /* Notify the Server DLLs */
51 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
53 /* Get the current Server DLL */
54 ServerDll
= CsrLoadedServerDll
[i
];
56 /* Make sure it's valid and that it has callback */
57 if ((ServerDll
) && (ServerDll
->HardErrorCallback
))
59 ServerDll
->HardErrorCallback(ThreadData
, HardErrorMessage
);
64 /* === INIT ROUTINES === */
67 * @name CsrSetProcessSecurity
69 * The CsrSetProcessSecurity routine protects access to the CSRSS process
70 * from unauthorized tampering.
74 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
82 CsrSetProcessSecurity(VOID
)
85 HANDLE hToken
, hProcess
= NtCurrentProcess();
87 PTOKEN_USER TokenInfo
= NULL
;
88 PSECURITY_DESCRIPTOR ProcSd
= NULL
;
93 Status
= NtOpenProcessToken(hProcess
, TOKEN_QUERY
, &hToken
);
94 if (!NT_SUCCESS(Status
)) goto Quickie
;
96 /* Get the Token User Length */
97 NtQueryInformationToken(hToken
, TokenUser
, NULL
, 0, &Length
);
99 /* Allocate space for it */
100 TokenInfo
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Length
);
103 Status
= STATUS_NO_MEMORY
;
107 /* Now query the data */
108 Status
= NtQueryInformationToken(hToken
, TokenUser
, TokenInfo
, Length
, &Length
);
110 if (!NT_SUCCESS(Status
)) goto Quickie
;
112 /* Now check the SID Length */
113 UserSid
= TokenInfo
->User
.Sid
;
114 Length
= RtlLengthSid(UserSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
116 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
117 ProcSd
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
120 Status
= STATUS_NO_MEMORY
;
124 /* Set the pointer to the DACL */
125 Dacl
= (PACL
)((ULONG_PTR
)ProcSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
127 /* Now create the SD itself */
128 Status
= RtlCreateSecurityDescriptor(ProcSd
, SECURITY_DESCRIPTOR_REVISION
);
129 if (!NT_SUCCESS(Status
))
131 DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status
);
135 /* Create the DACL for it*/
136 Status
= RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
137 if (!NT_SUCCESS(Status
))
139 DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status
);
144 Status
= RtlAddAccessAllowedAce(Dacl
,
146 PROCESS_VM_READ
| PROCESS_VM_WRITE
|
147 PROCESS_VM_OPERATION
| PROCESS_DUP_HANDLE
|
148 PROCESS_TERMINATE
| PROCESS_SUSPEND_RESUME
|
149 PROCESS_QUERY_INFORMATION
| READ_CONTROL
,
151 if (!NT_SUCCESS(Status
))
153 DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status
);
157 /* Clear the DACL in the SD */
158 Status
= RtlSetDaclSecurityDescriptor(ProcSd
, TRUE
, Dacl
, FALSE
);
159 if (!NT_SUCCESS(Status
))
161 DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status
);
165 /* Write the SD into the Process */
166 Status
= NtSetSecurityObject(hProcess
, DACL_SECURITY_INFORMATION
, ProcSd
);
167 if (!NT_SUCCESS(Status
))
169 DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status
);
173 /* Free the memory and return */
175 if (ProcSd
) RtlFreeHeap(CsrHeap
, 0, ProcSd
);
176 RtlFreeHeap(CsrHeap
, 0, TokenInfo
);
181 * @name CsrSetDirectorySecurity
183 * The CsrSetDirectorySecurity routine sets the security descriptor for the
184 * specified Object Directory.
186 * @param ObjectDirectory
187 * Handle fo the Object Directory to protect.
189 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
197 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory
)
199 /* FIXME: Implement */
200 return STATUS_SUCCESS
;
204 * @name GetDosDevicesProtection
206 * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
209 * @param DosDevicesSd
210 * Pointer to the Security Descriptor to return.
212 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
215 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
216 * regular users may or may not have full access to the directory.
221 GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd
)
223 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
224 SID_IDENTIFIER_AUTHORITY CreatorAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
225 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
226 PSID WorldSid
, CreatorSid
, AdminSid
, SystemSid
;
227 UCHAR KeyValueBuffer
[0x40];
228 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
229 UNICODE_STRING KeyName
;
230 ULONG ProtectionMode
= 0;
231 OBJECT_ATTRIBUTES ObjectAttributes
;
233 PACCESS_ALLOWED_ACE Ace
;
236 ULONG ResultLength
, SidLength
, AclLength
;
239 Status
= RtlCreateSecurityDescriptor(DosDevicesSd
, SECURITY_DESCRIPTOR_REVISION
);
240 ASSERT(NT_SUCCESS(Status
));
242 /* Initialize the System SID */
243 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
244 SECURITY_LOCAL_SYSTEM_RID
,
247 ASSERT(NT_SUCCESS(Status
));
249 /* Initialize the World SID */
250 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
, 1,
254 ASSERT(NT_SUCCESS(Status
));
256 /* Initialize the Admin SID */
257 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 2,
258 SECURITY_BUILTIN_DOMAIN_RID
,
259 DOMAIN_ALIAS_RID_ADMINS
,
262 ASSERT(NT_SUCCESS(Status
));
264 /* Initialize the Creator SID */
265 Status
= RtlAllocateAndInitializeSid(&CreatorAuthority
, 1,
266 SECURITY_CREATOR_OWNER_RID
,
269 ASSERT(NT_SUCCESS(Status
));
271 /* Open the Session Manager Key */
272 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
273 InitializeObjectAttributes(&ObjectAttributes
,
275 OBJ_CASE_INSENSITIVE
,
278 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
279 if (NT_SUCCESS(Status
))
281 /* Read the key value */
282 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
283 Status
= NtQueryValueKey(hKey
,
285 KeyValuePartialInformation
,
287 sizeof(KeyValueBuffer
),
290 /* Make sure it's what we expect it to be */
291 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
292 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
293 (*(PULONG
)KeyValuePartialInfo
->Data
))
295 /* Save the Protection Mode */
296 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
299 /* Close the handle */
303 /* Check the Protection Mode */
304 if (ProtectionMode
& 3)
306 /* Calculate SID Lengths */
307 SidLength
= RtlLengthSid(CreatorSid
) + RtlLengthSid(SystemSid
) +
308 RtlLengthSid(AdminSid
);
309 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
311 /* Allocate memory for the DACL */
312 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
313 ASSERT(Dacl
!= NULL
);
315 /* Build the ACL and add 3 ACEs */
316 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
317 ASSERT(NT_SUCCESS(Status
));
318 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
319 ASSERT(NT_SUCCESS(Status
));
320 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, AdminSid
);
321 ASSERT(NT_SUCCESS(Status
));
322 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, CreatorSid
);
323 ASSERT(NT_SUCCESS(Status
));
325 /* Edit the ACEs to make them inheritable */
326 Status
= RtlGetAce(Dacl
, 0, (PVOID
*)&Ace
);
327 ASSERT(NT_SUCCESS(Status
));
328 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
329 Status
= RtlGetAce(Dacl
, 1, (PVOID
*)&Ace
);
330 ASSERT(NT_SUCCESS(Status
));
331 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
332 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
333 ASSERT(NT_SUCCESS(Status
));
334 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
336 /* Set this DACL with the SD */
337 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
338 ASSERT(NT_SUCCESS(Status
));
343 /* Calculate SID Lengths */
344 SidLength
= RtlLengthSid(WorldSid
) + RtlLengthSid(SystemSid
);
345 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
347 /* Allocate memory for the DACL */
348 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
349 ASSERT(Dacl
!= NULL
);
351 /* Build the ACL and add 3 ACEs */
352 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
353 ASSERT(NT_SUCCESS(Status
));
354 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
, WorldSid
);
355 ASSERT(NT_SUCCESS(Status
));
356 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
357 ASSERT(NT_SUCCESS(Status
));
358 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, WorldSid
);
359 ASSERT(NT_SUCCESS(Status
));
361 /* Edit the last ACE to make it inheritable */
362 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
363 ASSERT(NT_SUCCESS(Status
));
364 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
366 /* Set this DACL with the SD */
367 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
368 ASSERT(NT_SUCCESS(Status
));
372 /* FIXME: failure cases! Fail: */
373 /* Free the memory */
374 RtlFreeHeap(CsrHeap
, 0, Dacl
);
376 /* FIXME: semi-failure cases! Quickie: */
379 RtlFreeSid(SystemSid
);
380 RtlFreeSid(WorldSid
);
381 RtlFreeSid(AdminSid
);
382 RtlFreeSid(CreatorSid
);
389 * @name FreeDosDevicesProtection
391 * The FreeDosDevicesProtection frees the security descriptor that was created
392 * by GetDosDevicesProtection
394 * @param DosDevicesSd
395 * Pointer to the security descriptor to free.
404 FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd
)
407 BOOLEAN Present
, Default
;
410 /* Get the DACL corresponding to this SD */
411 Status
= RtlGetDaclSecurityDescriptor(DosDevicesSd
, &Present
, &Dacl
, &Default
);
412 ASSERT(NT_SUCCESS(Status
));
414 ASSERT(Dacl
!= NULL
);
417 if ((NT_SUCCESS(Status
)) && (Dacl
)) RtlFreeHeap(CsrHeap
, 0, Dacl
);
421 * @name CsrCreateSessionObjectDirectory
423 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
424 * Session and Dos Devices directories for the specified session.
427 * Session ID for which to create the directories.
429 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
437 CsrCreateSessionObjectDirectory(IN ULONG Session
)
439 WCHAR SessionBuffer
[512], BnoBuffer
[512];
440 UNICODE_STRING SessionString
, BnoString
;
441 OBJECT_ATTRIBUTES ObjectAttributes
;
443 SECURITY_DESCRIPTOR DosDevicesSd
;
446 /* Generate the Session BNOLINKS Directory name */
447 swprintf(SessionBuffer
, L
"%ws\\BNOLINKS", SESSION_ROOT
);
448 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
451 InitializeObjectAttributes(&ObjectAttributes
,
453 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
456 Status
= NtCreateDirectoryObject(&BNOLinksDirectory
,
457 DIRECTORY_ALL_ACCESS
,
459 if (!NT_SUCCESS(Status
))
461 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
462 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
466 /* Now add the Session ID */
467 swprintf(SessionBuffer
, L
"%ld", Session
);
468 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
470 /* Check if this is the first Session */
473 /* Not the first, so the name will be slighly more complex */
474 swprintf(BnoBuffer
, L
"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT
, Session
);
475 RtlInitUnicodeString(&BnoString
, BnoBuffer
);
479 /* Use the direct name */
480 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
483 /* Create the symlink */
484 InitializeObjectAttributes(&ObjectAttributes
,
486 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
489 Status
= NtCreateSymbolicLinkObject(&BnoHandle
,
490 SYMBOLIC_LINK_ALL_ACCESS
,
493 if (!NT_SUCCESS(Status
))
495 DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
496 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
500 /* Create the \DosDevices Security Descriptor */
501 Status
= GetDosDevicesProtection(&DosDevicesSd
);
502 if (!NT_SUCCESS(Status
)) return Status
;
504 /* Now create a directory for this session */
505 swprintf(SessionBuffer
, L
"%ws\\%ld", SESSION_ROOT
, Session
);
506 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
508 /* Create the directory */
509 InitializeObjectAttributes(&ObjectAttributes
,
511 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
514 Status
= NtCreateDirectoryObject(&SessionObjectDirectory
,
515 DIRECTORY_ALL_ACCESS
,
517 if (!NT_SUCCESS(Status
))
519 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
520 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
521 FreeDosDevicesProtection(&DosDevicesSd
);
525 /* Next, create a directory for this session's DOS Devices */
526 RtlInitUnicodeString(&SessionString
, L
"DosDevices");
527 InitializeObjectAttributes(&ObjectAttributes
,
529 OBJ_CASE_INSENSITIVE
,
530 SessionObjectDirectory
,
532 Status
= NtCreateDirectoryObject(&DosDevicesDirectory
,
533 DIRECTORY_ALL_ACCESS
,
535 if (!NT_SUCCESS(Status
))
537 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
538 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
541 /* Release the Security Descriptor */
542 FreeDosDevicesProtection(&DosDevicesSd
);
549 * @name CsrParseServerCommandLine
551 * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
552 * registry and performs operations for each entry found.
554 * @param ArgumentCount
555 * Number of arguments on the command line.
558 * Array of arguments.
560 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
568 CsrParseServerCommandLine(IN ULONG ArgumentCount
,
569 IN PCHAR Arguments
[])
572 PCHAR ParameterName
= NULL
, ParameterValue
= NULL
, EntryPoint
, ServerString
;
574 ANSI_STRING AnsiString
;
575 OBJECT_ATTRIBUTES ObjectAttributes
;
577 /* Set the Defaults */
578 CsrTotalPerProcessDataLength
= 0;
579 CsrObjectDirectory
= NULL
;
580 CsrMaxApiRequestThreads
= 16;
582 /* Save our Session ID, and create a Directory for it */
583 SessionId
= NtCurrentPeb()->SessionId
;
584 Status
= CsrCreateSessionObjectDirectory(SessionId
);
585 if (!NT_SUCCESS(Status
))
587 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
590 /* It's not fatal if the session ID isn't zero */
591 if (SessionId
) return Status
;
592 ASSERT(NT_SUCCESS(Status
));
595 /* Loop through every argument */
596 for (i
= 1; i
< ArgumentCount
; i
++)
598 /* Split Name and Value */
599 ParameterName
= Arguments
[i
];
600 ParameterValue
= NULL
;
601 ParameterValue
= strchr(ParameterName
, '=');
602 if (ParameterValue
) *ParameterValue
++ = ANSI_NULL
;
603 DPRINT1("Name=%s, Value=%s\n", ParameterName
, ParameterValue
);
605 /* Check for Object Directory */
606 if (_stricmp(ParameterName
, "ObjectDirectory") == 0)
608 /* Check if a session ID is specified */
611 DPRINT1("Sessions not yet implemented\n");
615 /* Initialize the directory name */
616 RtlInitAnsiString(&AnsiString
, ParameterValue
);
617 Status
= RtlAnsiStringToUnicodeString(&CsrDirectoryName
,
620 ASSERT(NT_SUCCESS(Status
) || SessionId
!= 0);
621 if (!NT_SUCCESS(Status
)) return Status
;
624 InitializeObjectAttributes(&ObjectAttributes
,
626 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
629 Status
= NtCreateDirectoryObject(&CsrObjectDirectory
,
630 DIRECTORY_ALL_ACCESS
,
632 if (!NT_SUCCESS(Status
)) return Status
;
635 Status
= CsrSetDirectorySecurity(CsrObjectDirectory
);
636 if (!NT_SUCCESS(Status
)) return Status
;
638 else if (_stricmp(ParameterName
, "SubSystemType") == 0)
642 else if (_stricmp(ParameterName
, "MaxRequestThreads") == 0)
644 Status
= RtlCharToInteger(ParameterValue
,
646 &CsrMaxApiRequestThreads
);
648 else if (_stricmp(ParameterName
, "RequestThreads") == 0)
651 Status
= STATUS_SUCCESS
;
653 else if (_stricmp(ParameterName
, "ProfileControl") == 0)
657 else if (_stricmp(ParameterName
, "SharedSection") == 0)
659 /* Create the Section */
660 Status
= CsrSrvCreateSharedSection(ParameterValue
);
661 if (!NT_SUCCESS(Status
))
663 DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
664 ParameterName
, ParameterValue
, Status
);
669 Status
= CsrLoadServerDll("CSRSS" /* "CSRSRV" */, NULL
, CSRSRV_SERVERDLL_INDEX
);
671 else if (_stricmp(ParameterName
, "ServerDLL") == 0)
673 /* Loop the command line */
675 Status
= STATUS_INVALID_PARAMETER
;
676 ServerString
= ParameterValue
;
677 while (*ServerString
)
679 /* Check for the Entry Point */
680 if ((*ServerString
== ':') && (!EntryPoint
))
682 /* Found it. Add a nullchar and save it */
683 *ServerString
++ = ANSI_NULL
;
684 EntryPoint
= ServerString
;
687 /* Check for the Dll Index */
688 if (*ServerString
++ == ',') break;
691 /* Did we find something to load? */
694 DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
695 ParameterValue
, Status
);
699 /* Convert it to a ULONG */
700 Status
= RtlCharToInteger(ServerString
, 10, &DllIndex
);
702 /* Add a null char if it was valid */
703 if (NT_SUCCESS(Status
)) ServerString
[-1] = ANSI_NULL
;
706 if (CsrDebug
& 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue
, EntryPoint
);
707 Status
= CsrLoadServerDll(ParameterValue
, EntryPoint
, DllIndex
);
708 if (!NT_SUCCESS(Status
))
710 DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
711 ParameterValue
, Status
);
715 else if (_stricmp(ParameterName
, "Windows") == 0)
718 // Check whether we want to start in pure GUI or pure CLI.
722 /* Invalid parameter on the command line */
723 Status
= STATUS_INVALID_PARAMETER
;
732 * @name CsrCreateLocalSystemSD
734 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
735 * the local account with PORT_ALL_ACCESS.
737 * @param LocalSystemSd
738 * Pointer to a pointer to the security descriptor to create.
740 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
748 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR
*LocalSystemSd
)
750 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
753 PSECURITY_DESCRIPTOR SystemSd
;
757 /* Initialize the System SID */
758 RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
759 SECURITY_LOCAL_SYSTEM_RID
,
763 /* Get the length of the SID */
764 Length
= RtlLengthSid(SystemSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
766 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
767 SystemSd
= RtlAllocateHeap(CsrHeap
, 0, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
769 /* Set the pointer to the DACL */
770 Dacl
= (PACL
)((ULONG_PTR
)SystemSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
772 /* Now create the SD itself */
773 Status
= RtlCreateSecurityDescriptor(SystemSd
, SECURITY_DESCRIPTOR_REVISION
);
774 if (!NT_SUCCESS(Status
))
777 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
781 /* Create the DACL for it */
782 RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
785 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, PORT_ALL_ACCESS
, SystemSid
);
786 if (!NT_SUCCESS(Status
))
789 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
793 /* Clear the DACL in the SD */
794 Status
= RtlSetDaclSecurityDescriptor(SystemSd
, TRUE
, Dacl
, FALSE
);
795 if (!NT_SUCCESS(Status
))
798 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
802 /* Free the SID and return*/
803 RtlFreeSid(SystemSid
);
804 *LocalSystemSd
= SystemSd
;
809 * @name CsrSbApiPortInitialize
811 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
812 * communications with the Session Manager (SM) and initializes the static
813 * thread that will handle connection requests and APIs.
817 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
825 CsrSbApiPortInitialize(VOID
)
828 PSECURITY_DESCRIPTOR PortSd
;
829 OBJECT_ATTRIBUTES ObjectAttributes
;
831 HANDLE hRequestThread
;
834 /* Calculate how much space we'll need for the Port Name */
835 Size
= CsrDirectoryName
.Length
+ sizeof(SB_PORT_NAME
) + sizeof(WCHAR
);
837 /* Create the buffer for it */
838 CsrSbApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
839 if (!CsrSbApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
841 /* Setup the rest of the empty string */
842 CsrSbApiPortName
.Length
= 0;
843 CsrSbApiPortName
.MaximumLength
= (USHORT
)Size
;
845 /* Now append the full port name */
846 RtlAppendUnicodeStringToString(&CsrSbApiPortName
, &CsrDirectoryName
);
847 RtlAppendUnicodeToString(&CsrSbApiPortName
, UNICODE_PATH_SEP
);
848 RtlAppendUnicodeToString(&CsrSbApiPortName
, SB_PORT_NAME
);
849 if (CsrDebug
& 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName
);
851 /* Create Security Descriptor for this Port */
852 Status
= CsrCreateLocalSystemSD(&PortSd
);
853 if (!NT_SUCCESS(Status
)) return Status
;
855 /* Initialize the Attributes */
856 InitializeObjectAttributes(&ObjectAttributes
,
862 /* Create the Port Object */
863 Status
= NtCreatePort(&CsrSbApiPort
,
865 sizeof(SB_CONNECTION_INFO
),
867 32 * sizeof(SB_API_MSG
));
868 if (PortSd
) RtlFreeHeap(CsrHeap
, 0, PortSd
);
870 if (NT_SUCCESS(Status
))
872 /* Create the Thread to handle the API Requests */
873 Status
= RtlCreateUserThread(NtCurrentProcess(),
879 (PVOID
)CsrSbApiRequestThread
,
883 if (NT_SUCCESS(Status
))
885 /* Add it as a Static Server Thread */
886 CsrSbApiRequestThreadPtr
= CsrAddStaticServerThread(hRequestThread
,
891 Status
= NtResumeThread(hRequestThread
, NULL
);
899 /* PUBLIC FUNCTIONS ***********************************************************/
902 * @name CsrServerInitialization
905 * The CsrServerInitialization routine is the native (not Server) entrypoint
906 * of this Server DLL. It serves as the entrypoint for csrss.
908 * @param ArgumentCount
909 * Number of arguments on the command line.
912 * Array of arguments from the command line.
914 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
922 CsrServerInitialization(IN ULONG ArgumentCount
,
923 IN PCHAR Arguments
[])
925 NTSTATUS Status
= STATUS_SUCCESS
;
926 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
928 /* Create the Init Event */
929 Status
= NtCreateEvent(&CsrInitializationEvent
,
932 SynchronizationEvent
,
934 if (!NT_SUCCESS(Status
))
936 DPRINT1("CSRSRV:%s: NtCreateEvent failed (Status=%08lx)\n",
937 __FUNCTION__
, Status
);
941 /* Cache System Basic Information so we don't always request it */
942 Status
= NtQuerySystemInformation(SystemBasicInformation
,
944 sizeof(SYSTEM_BASIC_INFORMATION
),
946 if (!NT_SUCCESS(Status
))
948 DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=%08lx)\n",
949 __FUNCTION__
, Status
);
954 CsrHeap
= RtlGetProcessHeap();
956 /* Set our Security Descriptor to protect the process */
957 Status
= CsrSetProcessSecurity();
958 if (!NT_SUCCESS(Status
))
960 DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=%08lx)\n",
961 __FUNCTION__
, Status
);
965 /* Set up Session Support */
966 Status
= CsrInitializeNtSessionList();
967 if (!NT_SUCCESS(Status
))
969 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
970 __FUNCTION__
, Status
);
974 /* Set up Process Support */
975 Status
= CsrInitializeProcessStructure();
976 if (!NT_SUCCESS(Status
))
978 DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=%08lx)\n",
979 __FUNCTION__
, Status
);
983 /* Parse the command line */
984 Status
= CsrParseServerCommandLine(ArgumentCount
, Arguments
);
985 if (!NT_SUCCESS(Status
))
987 DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=%08lx)\n",
988 __FUNCTION__
, Status
);
992 /* Now initialize our API Port */
993 Status
= CsrApiPortInitialize();
994 if (!NT_SUCCESS(Status
))
996 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n",
997 __FUNCTION__
, Status
);
1001 /* Initialize the API Port for SM communication */
1002 Status
= CsrSbApiPortInitialize();
1003 if (!NT_SUCCESS(Status
))
1005 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n",
1006 __FUNCTION__
, Status
);
1010 /* We're all set! Connect to SM! */
1011 Status
= SmConnectToSm(&CsrSbApiPortName
,
1013 IMAGE_SUBSYSTEM_WINDOWS_GUI
,
1015 if (!NT_SUCCESS(Status
))
1017 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n",
1018 __FUNCTION__
, Status
);
1022 /* Finito! Signal the event */
1023 Status
= NtSetEvent(CsrInitializationEvent
, NULL
);
1024 if (!NT_SUCCESS(Status
))
1026 DPRINT1("CSRSRV:%s: NtSetEvent failed (Status=%08lx)\n",
1027 __FUNCTION__
, Status
);
1031 /* Close the event handle now */
1032 NtClose(CsrInitializationEvent
);
1034 /* Have us handle Hard Errors */
1035 Status
= NtSetDefaultHardErrorPort(CsrApiPort
);
1036 if (!NT_SUCCESS(Status
))
1038 DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n",
1039 __FUNCTION__
, Status
);
1048 * @name CsrPopulateDosDevices
1049 * @unimplemented NT5.1
1051 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1052 * to populate the Dos Devices Object Directory for the session.
1063 CsrPopulateDosDevices(VOID
)
1065 DPRINT1("Deprecated API in r55585.\n");
1071 DllMain(IN HANDLE hDll
,
1073 IN LPVOID lpReserved
)
1075 /* We don't do much */
1076 UNREFERENCED_PARAMETER(hDll
);
1077 UNREFERENCED_PARAMETER(dwReason
);
1078 UNREFERENCED_PARAMETER(lpReserved
);