2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR SubSystem
4 * FILE: subsystems/win32/csrss/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
= (HANDLE
) 0;
20 HANDLE CsrObjectDirectory
= (HANDLE
) 0;
21 UNICODE_STRING CsrDirectoryName
;
22 UNICODE_STRING CsrSbApiPortName
;
23 HANDLE CsrSbApiPort
= 0;
24 PCSR_THREAD CsrSbApiRequestThreadPtr
;
26 HANDLE hSbApiPort
= (HANDLE
) 0;
27 HANDLE CsrApiPort
= (HANDLE
) 0;
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
;
38 /* PRIVATE FUNCTIONS **********************************************************/
41 CallHardError(IN PCSR_THREAD ThreadData
,
42 IN PHARDERROR_MSG HardErrorMessage
)
45 PCSR_SERVER_DLL ServerDll
;
47 DPRINT("CSR: %s called\n", __FUNCTION__
);
49 /* Notify the Server DLLs */
50 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
52 /* Get the current Server DLL */
53 ServerDll
= CsrLoadedServerDll
[i
];
55 /* Make sure it's valid and that it has callback */
56 if ((ServerDll
) && (ServerDll
->HardErrorCallback
))
58 ServerDll
->HardErrorCallback(ThreadData
, HardErrorMessage
);
65 CallProcessCreated(IN PCSR_PROCESS SourceProcessData
,
66 IN PCSR_PROCESS TargetProcessData
)
68 NTSTATUS Status
= STATUS_SUCCESS
;
70 PCSR_SERVER_DLL ServerDll
;
72 DPRINT("CSR: %s called\n", __FUNCTION__
);
74 /* Notify the Server DLLs */
75 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
77 /* Get the current Server DLL */
78 ServerDll
= CsrLoadedServerDll
[i
];
80 /* Make sure it's valid and that it has callback */
81 if ((ServerDll
) && (ServerDll
->NewProcessCallback
))
83 Status
= ServerDll
->NewProcessCallback(SourceProcessData
, TargetProcessData
);
91 CSRSS_API_DEFINITION NativeDefinitions
[] =
93 CSRSS_DEFINE_API(REGISTER_SERVICES_PROCESS
, SrvRegisterServicesProcess
), // winsrv.dll
96 /* === INIT ROUTINES === */
99 * @name CsrSetProcessSecurity
101 * The CsrSetProcessSecurity routine protects access to the CSRSS process
102 * from unauthorized tampering.
106 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
114 CsrSetProcessSecurity(VOID
)
117 HANDLE hToken
, hProcess
= NtCurrentProcess();
119 PTOKEN_USER TokenInfo
= NULL
;
120 PSECURITY_DESCRIPTOR ProcSd
= NULL
;
125 Status
= NtOpenProcessToken(hProcess
, TOKEN_QUERY
, &hToken
);
126 if (!NT_SUCCESS(Status
)) goto Quickie
;
128 /* Get the Token User Length */
129 NtQueryInformationToken(hToken
, TokenUser
, NULL
, 0, &Length
);
131 /* Allocate space for it */
132 TokenInfo
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Length
);
135 Status
= STATUS_NO_MEMORY
;
139 /* Now query the data */
140 Status
= NtQueryInformationToken(hToken
, TokenUser
, TokenInfo
, Length
, &Length
);
142 if (!NT_SUCCESS(Status
)) goto Quickie
;
144 /* Now check the SID Length */
145 UserSid
= TokenInfo
->User
.Sid
;
146 Length
= RtlLengthSid(UserSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
148 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
149 ProcSd
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
152 Status
= STATUS_NO_MEMORY
;
156 /* Set the pointer to the DACL */
157 Dacl
= (PACL
)((ULONG_PTR
)ProcSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
159 /* Now create the SD itself */
160 Status
= RtlCreateSecurityDescriptor(ProcSd
, SECURITY_DESCRIPTOR_REVISION
);
161 if (!NT_SUCCESS(Status
))
163 DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status
);
167 /* Create the DACL for it*/
168 Status
= RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
169 if (!NT_SUCCESS(Status
))
171 DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status
);
176 Status
= RtlAddAccessAllowedAce(Dacl
,
178 PROCESS_VM_READ
| PROCESS_VM_WRITE
|
179 PROCESS_VM_OPERATION
| PROCESS_DUP_HANDLE
|
180 PROCESS_TERMINATE
| PROCESS_SUSPEND_RESUME
|
181 PROCESS_QUERY_INFORMATION
| READ_CONTROL
,
183 if (!NT_SUCCESS(Status
))
185 DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status
);
189 /* Clear the DACL in the SD */
190 Status
= RtlSetDaclSecurityDescriptor(ProcSd
, TRUE
, Dacl
, FALSE
);
191 if (!NT_SUCCESS(Status
))
193 DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status
);
197 /* Write the SD into the Process */
198 Status
= NtSetSecurityObject(hProcess
, DACL_SECURITY_INFORMATION
, ProcSd
);
199 if (!NT_SUCCESS(Status
))
201 DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status
);
205 /* Free the memory and return */
207 if (ProcSd
) RtlFreeHeap(CsrHeap
, 0, ProcSd
);
208 RtlFreeHeap(CsrHeap
, 0, TokenInfo
);
213 * @name CsrSetDirectorySecurity
215 * The CsrSetDirectorySecurity routine sets the security descriptor for the
216 * specified Object Directory.
218 * @param ObjectDirectory
219 * Handle fo the Object Directory to protect.
221 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
229 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory
)
231 /* FIXME: Implement */
232 return STATUS_SUCCESS
;
236 * @name GetDosDevicesProtection
238 * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
241 * @param DosDevicesSd
242 * Pointer to the Security Descriptor to return.
244 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
247 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
248 * regular users may or may not have full access to the directory.
253 GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd
)
255 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
256 SID_IDENTIFIER_AUTHORITY CreatorAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
257 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
258 PSID WorldSid
, CreatorSid
, AdminSid
, SystemSid
;
259 UCHAR KeyValueBuffer
[0x40];
260 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
261 UNICODE_STRING KeyName
;
262 ULONG ProtectionMode
= 0;
263 OBJECT_ATTRIBUTES ObjectAttributes
;
265 PACCESS_ALLOWED_ACE Ace
;
268 ULONG ResultLength
, SidLength
, AclLength
;
271 Status
= RtlCreateSecurityDescriptor(DosDevicesSd
, SECURITY_DESCRIPTOR_REVISION
);
272 ASSERT(NT_SUCCESS(Status
));
274 /* Initialize the System SID */
275 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
276 SECURITY_LOCAL_SYSTEM_RID
,
279 ASSERT(NT_SUCCESS(Status
));
281 /* Initialize the World SID */
282 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
, 1,
286 ASSERT(NT_SUCCESS(Status
));
288 /* Initialize the Admin SID */
289 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 2,
290 SECURITY_BUILTIN_DOMAIN_RID
,
291 DOMAIN_ALIAS_RID_ADMINS
,
294 ASSERT(NT_SUCCESS(Status
));
296 /* Initialize the Creator SID */
297 Status
= RtlAllocateAndInitializeSid(&CreatorAuthority
, 1,
298 SECURITY_CREATOR_OWNER_RID
,
301 ASSERT(NT_SUCCESS(Status
));
303 /* Open the Session Manager Key */
304 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
305 InitializeObjectAttributes(&ObjectAttributes
,
307 OBJ_CASE_INSENSITIVE
,
310 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
311 if (NT_SUCCESS(Status
))
313 /* Read the key value */
314 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
315 Status
= NtQueryValueKey(hKey
,
317 KeyValuePartialInformation
,
319 sizeof(KeyValueBuffer
),
322 /* Make sure it's what we expect it to be */
323 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
324 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
325 (*(PULONG
)KeyValuePartialInfo
->Data
))
327 /* Save the Protection Mode */
328 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
331 /* Close the handle */
335 /* Check the Protection Mode */
336 if (ProtectionMode
& 3)
338 /* Calculate SID Lengths */
339 SidLength
= RtlLengthSid(CreatorSid
) + RtlLengthSid(SystemSid
) +
340 RtlLengthSid(AdminSid
);
341 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
343 /* Allocate memory for the DACL */
344 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
345 ASSERT(Dacl
!= NULL
);
347 /* Build the ACL and add 3 ACEs */
348 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
349 ASSERT(NT_SUCCESS(Status
));
350 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
351 ASSERT(NT_SUCCESS(Status
));
352 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, AdminSid
);
353 ASSERT(NT_SUCCESS(Status
));
354 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, CreatorSid
);
355 ASSERT(NT_SUCCESS(Status
));
357 /* Edit the ACEs to make them inheritable */
358 Status
= RtlGetAce(Dacl
, 0, (PVOID
*)&Ace
);
359 ASSERT(NT_SUCCESS(Status
));
360 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
361 Status
= RtlGetAce(Dacl
, 1, (PVOID
*)&Ace
);
362 ASSERT(NT_SUCCESS(Status
));
363 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
364 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
365 ASSERT(NT_SUCCESS(Status
));
366 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
368 /* Set this DACL with the SD */
369 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
370 ASSERT(NT_SUCCESS(Status
));
375 /* Calculate SID Lengths */
376 SidLength
= RtlLengthSid(WorldSid
) + RtlLengthSid(SystemSid
);
377 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
379 /* Allocate memory for the DACL */
380 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
381 ASSERT(Dacl
!= NULL
);
383 /* Build the ACL and add 3 ACEs */
384 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
385 ASSERT(NT_SUCCESS(Status
));
386 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
, WorldSid
);
387 ASSERT(NT_SUCCESS(Status
));
388 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
389 ASSERT(NT_SUCCESS(Status
));
390 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, WorldSid
);
391 ASSERT(NT_SUCCESS(Status
));
393 /* Edit the last ACE to make it inheritable */
394 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
395 ASSERT(NT_SUCCESS(Status
));
396 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
398 /* Set this DACL with the SD */
399 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
400 ASSERT(NT_SUCCESS(Status
));
404 /* FIXME: failure cases! Fail: */
405 /* Free the memory */
406 RtlFreeHeap(CsrHeap
, 0, Dacl
);
408 /* FIXME: semi-failure cases! Quickie: */
411 RtlFreeSid(SystemSid
);
412 RtlFreeSid(WorldSid
);
413 RtlFreeSid(AdminSid
);
414 RtlFreeSid(CreatorSid
);
421 * @name FreeDosDevicesProtection
423 * The FreeDosDevicesProtection frees the security descriptor that was created
424 * by GetDosDevicesProtection
426 * @param DosDevicesSd
427 * Pointer to the security descriptor to free.
436 FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd
)
439 BOOLEAN Present
, Default
;
442 /* Get the DACL corresponding to this SD */
443 Status
= RtlGetDaclSecurityDescriptor(DosDevicesSd
, &Present
, &Dacl
, &Default
);
444 ASSERT(NT_SUCCESS(Status
));
446 ASSERT(Dacl
!= NULL
);
449 if ((NT_SUCCESS(Status
)) && (Dacl
)) RtlFreeHeap(CsrHeap
, 0, Dacl
);
453 * @name CsrCreateSessionObjectDirectory
455 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
456 * Session and Dos Devices directories for the specified session.
459 * Session ID for which to create the directories.
461 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
469 CsrCreateSessionObjectDirectory(IN ULONG Session
)
471 WCHAR SessionBuffer
[512], BnoBuffer
[512];
472 UNICODE_STRING SessionString
, BnoString
;
473 OBJECT_ATTRIBUTES ObjectAttributes
;
475 SECURITY_DESCRIPTOR DosDevicesSd
;
478 /* Generate the Session BNOLINKS Directory name */
479 swprintf(SessionBuffer
, L
"%ws\\BNOLINKS", SESSION_ROOT
);
480 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
483 InitializeObjectAttributes(&ObjectAttributes
,
485 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
488 Status
= NtCreateDirectoryObject(&BNOLinksDirectory
,
489 DIRECTORY_ALL_ACCESS
,
491 if (!NT_SUCCESS(Status
))
493 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
494 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
498 /* Now add the Session ID */
499 swprintf(SessionBuffer
, L
"%ld", Session
);
500 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
502 /* Check if this is the first Session */
505 /* Not the first, so the name will be slighly more complex */
506 swprintf(BnoBuffer
, L
"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT
, Session
);
507 RtlInitUnicodeString(&BnoString
, BnoBuffer
);
511 /* Use the direct name */
512 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
515 /* Create the symlink */
516 InitializeObjectAttributes(&ObjectAttributes
,
518 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
521 Status
= NtCreateSymbolicLinkObject(&BnoHandle
,
522 SYMBOLIC_LINK_ALL_ACCESS
,
525 if (!NT_SUCCESS(Status
))
527 DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
528 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
532 /* Create the \DosDevices Security Descriptor */
533 Status
= GetDosDevicesProtection(&DosDevicesSd
);
534 if (!NT_SUCCESS(Status
)) return Status
;
536 /* Now create a directory for this session */
537 swprintf(SessionBuffer
, L
"%ws\\%ld", SESSION_ROOT
, Session
);
538 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
540 /* Create the directory */
541 InitializeObjectAttributes(&ObjectAttributes
,
543 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
546 Status
= NtCreateDirectoryObject(&SessionObjectDirectory
,
547 DIRECTORY_ALL_ACCESS
,
549 if (!NT_SUCCESS(Status
))
551 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
552 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
553 FreeDosDevicesProtection(&DosDevicesSd
);
557 /* Next, create a directory for this session's DOS Devices */
558 RtlInitUnicodeString(&SessionString
, L
"DosDevices");
559 InitializeObjectAttributes(&ObjectAttributes
,
561 OBJ_CASE_INSENSITIVE
,
562 SessionObjectDirectory
,
564 Status
= NtCreateDirectoryObject(&DosDevicesDirectory
,
565 DIRECTORY_ALL_ACCESS
,
567 if (!NT_SUCCESS(Status
))
569 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
570 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
573 /* Release the Security Descriptor */
574 FreeDosDevicesProtection(&DosDevicesSd
);
581 * @name CsrParseServerCommandLine
583 * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
584 * registry and performs operations for each entry found.
586 * @param ArgumentCount
587 * Number of arguments on the command line.
590 * Array of arguments.
592 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
600 CsrParseServerCommandLine(IN ULONG ArgumentCount
,
601 IN PCHAR Arguments
[])
604 PCHAR ParameterName
= NULL
, ParameterValue
= NULL
, EntryPoint
, ServerString
;
606 ANSI_STRING AnsiString
;
607 OBJECT_ATTRIBUTES ObjectAttributes
;
609 /* Set the Defaults */
610 CsrTotalPerProcessDataLength
= 0;
611 CsrObjectDirectory
= NULL
;
612 CsrMaxApiRequestThreads
= 16;
614 /* Save our Session ID, and create a Directory for it */
615 SessionId
= NtCurrentPeb()->SessionId
;
616 Status
= CsrCreateSessionObjectDirectory(SessionId
);
617 if (!NT_SUCCESS(Status
))
619 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
622 /* It's not fatal if the session ID isn't zero */
623 if (SessionId
) return Status
;
624 ASSERT(NT_SUCCESS(Status
));
627 /* Loop through every argument */
628 for (i
= 1; i
< ArgumentCount
; i
++)
630 /* Split Name and Value */
631 ParameterName
= Arguments
[i
];
632 ParameterValue
= NULL
;
633 ParameterValue
= strchr(ParameterName
, '=');
634 if (ParameterValue
) *ParameterValue
++ = ANSI_NULL
;
635 DPRINT1("Name=%s, Value=%s\n", ParameterName
, ParameterValue
);
637 /* Check for Object Directory */
638 if (_stricmp(ParameterName
, "ObjectDirectory") == 0)
640 /* Check if a session ID is specified */
643 DPRINT1("Sessions not yet implemented\n");
647 /* Initialize the directory name */
648 RtlInitAnsiString(&AnsiString
, ParameterValue
);
649 Status
= RtlAnsiStringToUnicodeString(&CsrDirectoryName
,
652 ASSERT(NT_SUCCESS(Status
) || SessionId
!= 0);
653 if (!NT_SUCCESS(Status
)) return Status
;
656 InitializeObjectAttributes(&ObjectAttributes
,
658 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
661 Status
= NtCreateDirectoryObject(&CsrObjectDirectory
,
662 DIRECTORY_ALL_ACCESS
,
664 if (!NT_SUCCESS(Status
)) return Status
;
667 Status
= CsrSetDirectorySecurity(CsrObjectDirectory
);
668 if (!NT_SUCCESS(Status
)) return Status
;
670 else if (_stricmp(ParameterName
, "SubSystemType") == 0)
674 else if (_stricmp(ParameterName
, "MaxRequestThreads") == 0)
676 Status
= RtlCharToInteger(ParameterValue
,
678 &CsrMaxApiRequestThreads
);
680 else if (_stricmp(ParameterName
, "RequestThreads") == 0)
683 Status
= STATUS_SUCCESS
;
685 else if (_stricmp(ParameterName
, "ProfileControl") == 0)
689 else if (_stricmp(ParameterName
, "SharedSection") == 0)
691 /* Create the Section */
692 Status
= CsrSrvCreateSharedSection(ParameterValue
);
693 if (!NT_SUCCESS(Status
))
695 DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
696 ParameterName
, ParameterValue
, Status
);
701 Status
= CsrLoadServerDll("CSRSS" /* "CSRSRV" */, NULL
, CSRSRV_SERVERDLL_INDEX
);
703 else if (_stricmp(ParameterName
, "ServerDLL") == 0)
705 /* Loop the command line */
707 Status
= STATUS_INVALID_PARAMETER
;
708 ServerString
= ParameterValue
;
709 while (*ServerString
)
711 /* Check for the Entry Point */
712 if ((*ServerString
== ':') && (!EntryPoint
))
714 /* Found it. Add a nullchar and save it */
715 *ServerString
++ = ANSI_NULL
;
716 EntryPoint
= ServerString
;
719 /* Check for the Dll Index */
720 if (*ServerString
++ == ',') break;
723 /* Did we find something to load? */
726 DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
727 ParameterValue
, Status
);
731 /* Convert it to a ULONG */
732 Status
= RtlCharToInteger(ServerString
, 10, &DllIndex
);
734 /* Add a null char if it was valid */
735 if (NT_SUCCESS(Status
)) ServerString
[-1] = ANSI_NULL
;
738 if (CsrDebug
& 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue
, EntryPoint
);
739 Status
= CsrLoadServerDll(ParameterValue
, EntryPoint
, DllIndex
);
740 if (!NT_SUCCESS(Status
))
742 DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
743 ParameterValue
, Status
);
747 else if (_stricmp(ParameterName
, "Windows") == 0)
750 // Check whether we want to start in pure GUI or pure CLI.
754 /* Invalid parameter on the command line */
755 Status
= STATUS_INVALID_PARAMETER
;
764 * @name CsrCreateLocalSystemSD
766 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
767 * the local account with PORT_ALL_ACCESS.
769 * @param LocalSystemSd
770 * Pointer to a pointer to the security descriptor to create.
772 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
780 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR
*LocalSystemSd
)
782 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
785 PSECURITY_DESCRIPTOR SystemSd
;
789 /* Initialize the System SID */
790 RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
791 SECURITY_LOCAL_SYSTEM_RID
,
795 /* Get the length of the SID */
796 Length
= RtlLengthSid(SystemSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
798 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
799 SystemSd
= RtlAllocateHeap(CsrHeap
, 0, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
801 /* Set the pointer to the DACL */
802 Dacl
= (PACL
)((ULONG_PTR
)SystemSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
804 /* Now create the SD itself */
805 Status
= RtlCreateSecurityDescriptor(SystemSd
, SECURITY_DESCRIPTOR_REVISION
);
806 if (!NT_SUCCESS(Status
))
809 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
813 /* Create the DACL for it */
814 RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
817 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, PORT_ALL_ACCESS
, SystemSid
);
818 if (!NT_SUCCESS(Status
))
821 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
825 /* Clear the DACL in the SD */
826 Status
= RtlSetDaclSecurityDescriptor(SystemSd
, TRUE
, Dacl
, FALSE
);
827 if (!NT_SUCCESS(Status
))
830 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
834 /* Free the SID and return*/
835 RtlFreeSid(SystemSid
);
836 *LocalSystemSd
= SystemSd
;
841 * @name CsrSbApiPortInitialize
843 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
844 * communications with the Session Manager (SM) and initializes the static
845 * thread that will handle connection requests and APIs.
849 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
857 CsrSbApiPortInitialize(VOID
)
860 PSECURITY_DESCRIPTOR PortSd
;
861 OBJECT_ATTRIBUTES ObjectAttributes
;
863 HANDLE hRequestThread
;
866 /* Calculate how much space we'll need for the Port Name */
867 Size
= CsrDirectoryName
.Length
+ sizeof(SB_PORT_NAME
) + sizeof(WCHAR
);
869 /* Create the buffer for it */
870 CsrSbApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
871 if (!CsrSbApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
873 /* Setup the rest of the empty string */
874 CsrSbApiPortName
.Length
= 0;
875 CsrSbApiPortName
.MaximumLength
= (USHORT
)Size
;
877 /* Now append the full port name */
878 RtlAppendUnicodeStringToString(&CsrSbApiPortName
, &CsrDirectoryName
);
879 RtlAppendUnicodeToString(&CsrSbApiPortName
, UNICODE_PATH_SEP
);
880 RtlAppendUnicodeToString(&CsrSbApiPortName
, SB_PORT_NAME
);
881 if (CsrDebug
& 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName
);
883 /* Create Security Descriptor for this Port */
884 Status
= CsrCreateLocalSystemSD(&PortSd
);
885 if (!NT_SUCCESS(Status
)) return Status
;
887 /* Initialize the Attributes */
888 InitializeObjectAttributes(&ObjectAttributes
,
894 /* Create the Port Object */
895 Status
= NtCreatePort(&CsrSbApiPort
,
897 sizeof(SB_CONNECTION_INFO
),
899 32 * sizeof(SB_API_MSG
));
900 if (PortSd
) RtlFreeHeap(CsrHeap
, 0, PortSd
);
902 if (NT_SUCCESS(Status
))
904 /* Create the Thread to handle the API Requests */
905 Status
= RtlCreateUserThread(NtCurrentProcess(),
911 (PVOID
)CsrSbApiRequestThread
,
915 if (NT_SUCCESS(Status
))
917 /* Add it as a Static Server Thread */
918 CsrSbApiRequestThreadPtr
= CsrAddStaticServerThread(hRequestThread
,
923 Status
= NtResumeThread(hRequestThread
, NULL
);
932 /* PUBLIC FUNCTIONS ***********************************************************/
935 * @name CsrServerInitialization
938 * The CsrServerInitialization routine is the native (not Server) entrypoint
939 * of this Server DLL. It serves as the entrypoint for csrss.
941 * @param ArgumentCount
942 * Number of arguments on the command line.
945 * Array of arguments from the command line.
947 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
955 CsrServerInitialization(IN ULONG ArgumentCount
,
956 IN PCHAR Arguments
[])
958 NTSTATUS Status
= STATUS_SUCCESS
;
959 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
961 /* Create the Init Event */
962 Status
= NtCreateEvent(&CsrInitializationEvent
,
965 SynchronizationEvent
,
967 if (!NT_SUCCESS(Status
))
969 DPRINT1("CSRSRV:%s: NtCreateEvent failed (Status=%08lx)\n",
970 __FUNCTION__
, Status
);
974 /* Cache System Basic Information so we don't always request it */
975 Status
= NtQuerySystemInformation(SystemBasicInformation
,
977 sizeof(SYSTEM_BASIC_INFORMATION
),
979 if (!NT_SUCCESS(Status
))
981 DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=%08lx)\n",
982 __FUNCTION__
, Status
);
987 CsrHeap
= RtlGetProcessHeap();
989 /* Set our Security Descriptor to protect the process */
990 Status
= CsrSetProcessSecurity();
991 if (!NT_SUCCESS(Status
))
993 DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=%08lx)\n",
994 __FUNCTION__
, Status
);
998 /* Set up Session Support */
999 Status
= CsrInitializeNtSessionList();
1000 if (!NT_SUCCESS(Status
))
1002 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
1003 __FUNCTION__
, Status
);
1007 /* Set up Process Support */
1008 Status
= CsrInitializeProcessStructure();
1009 if (!NT_SUCCESS(Status
))
1011 DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=%08lx)\n",
1012 __FUNCTION__
, Status
);
1016 /* Parse the command line */
1017 Status
= CsrParseServerCommandLine(ArgumentCount
, Arguments
);
1018 if (!NT_SUCCESS(Status
))
1020 DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=%08lx)\n",
1021 __FUNCTION__
, Status
);
1026 Status
= CsrApiRegisterDefinitions(NativeDefinitions
);
1027 if (!NT_SUCCESS(Status
))
1029 DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrApiRegisterDefinitions", Status
);
1033 /* Now initialize our API Port */
1034 Status
= CsrApiPortInitialize();
1035 if (!NT_SUCCESS(Status
))
1037 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n",
1038 __FUNCTION__
, Status
);
1042 /* Initialize the API Port for SM communication */
1043 Status
= CsrSbApiPortInitialize();
1044 if (!NT_SUCCESS(Status
))
1046 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n",
1047 __FUNCTION__
, Status
);
1051 /* We're all set! Connect to SM! */
1052 Status
= SmConnectToSm(&CsrSbApiPortName
,
1054 IMAGE_SUBSYSTEM_WINDOWS_GUI
,
1056 if (!NT_SUCCESS(Status
))
1058 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n",
1059 __FUNCTION__
, Status
);
1063 /* Finito! Signal the event */
1064 Status
= NtSetEvent(CsrInitializationEvent
, NULL
);
1065 if (!NT_SUCCESS(Status
))
1067 DPRINT1("CSRSRV:%s: NtSetEvent failed (Status=%08lx)\n",
1068 __FUNCTION__
, Status
);
1072 /* Close the event handle now */
1073 NtClose(CsrInitializationEvent
);
1075 /* Have us handle Hard Errors */
1076 Status
= NtSetDefaultHardErrorPort(CsrApiPort
);
1077 if (!NT_SUCCESS(Status
))
1079 DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n",
1080 __FUNCTION__
, Status
);
1089 * @name CsrPopulateDosDevices
1090 * @unimplemented NT5.1
1092 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1093 * to populate the Dos Devices Object Directory for the session.
1104 CsrPopulateDosDevices(VOID
)
1106 DPRINT1("Deprecated API\n");
1112 DllMain(IN HANDLE hDll
,
1114 IN LPVOID lpReserved
)
1116 /* We don't do much */
1117 UNREFERENCED_PARAMETER(hDll
);
1118 UNREFERENCED_PARAMETER(dwReason
);
1119 UNREFERENCED_PARAMETER(lpReserved
);