2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsys/csr/csrsrv/init.c
5 * PURPOSE: CSR Server DLL Initialization
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* DATA **********************************************************************/
18 HANDLE CsrObjectDirectory
;
20 BOOLEAN CsrProfileControl
;
21 UNICODE_STRING CsrDirectoryName
;
23 HANDLE BNOLinksDirectory
;
24 HANDLE SessionObjectDirectory
;
25 HANDLE DosDevicesDirectory
;
26 HANDLE CsrInitializationEvent
;
27 SYSTEM_BASIC_INFORMATION CsrNtSysInfo
;
29 /* PRIVATE FUNCTIONS *********************************************************/
32 * @name CsrPopulateDosDevicesDirectory
34 * The CsrPopulateDosDevicesDirectory routine uses the DOS Device Map from the
35 * Kernel to populate the Dos Devices Object Directory for the session.
46 CsrPopulateDosDevicesDirectory(IN HANDLE hDosDevicesDirectory
,
47 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMap
)
49 WCHAR SymLinkBuffer
[0x1000];
50 UNICODE_STRING GlobalString
;
51 OBJECT_ATTRIBUTES ObjectAttributes
;
52 HANDLE hDirectory
= 0;
54 ULONG ReturnLength
= 0;
55 ULONG BufferLength
= 0x4000;
57 POBJECT_DIRECTORY_INFORMATION QueryBuffer
;
59 UNICODE_STRING LinkTarget
;
61 /* Initialize the Global String */
62 RtlInitUnicodeString(&GlobalString
, GLOBAL_ROOT
);
64 /* Initialize the Object Attributes */
65 InitializeObjectAttributes(&ObjectAttributes
,
71 /* Open the directory */
72 Status
= NtOpenDirectoryObject(&hDirectory
,
75 if (!NT_SUCCESS(Status
)) return Status
;
78 QueryBuffer
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, 0x4000);
79 if (!QueryBuffer
) return STATUS_NO_MEMORY
;
81 /* Start query loop */
84 /* Query the Directory */
85 Status
= NtQueryDirectoryObject(hDirectory
,
93 /* Check for the status */
94 if (NT_SUCCESS(Status
))
96 /* Make sure it has a name */
97 if (!QueryBuffer
->ObjectName
.Buffer
[0]) continue;
99 /* Check if it's actually a symbolic link */
100 if (wcscmp(QueryBuffer
->ObjectTypeName
.Buffer
, SYMLINK_NAME
))
103 InitializeObjectAttributes(&ObjectAttributes
,
104 &QueryBuffer
->ObjectName
,
105 OBJ_CASE_INSENSITIVE
,
108 Status
= NtOpenSymbolicLinkObject(&hSymLink
,
111 if (NT_SUCCESS(Status
))
113 /* Setup the Target String */
114 LinkTarget
.Length
= 0;
115 LinkTarget
.MaximumLength
= sizeof(SymLinkBuffer
);
116 LinkTarget
.Buffer
= SymLinkBuffer
;
118 /* Query the target */
119 Status
= NtQuerySymbolicLinkObject(hSymLink
,
123 /* Close the handle */
133 * @name CsrLoadServerDllFromCommandLine
135 * The CsrLoadServerDllFromCommandLine routine loads a Server DLL from the
136 * CSRSS command-line in the registry.
139 * Pointer to the specially formatted string for this Server DLL.
141 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
149 CsrLoadServerDllFromCommandLine(PCHAR KeyValue
)
151 PCHAR EntryPoint
= NULL
;
153 PCHAR ServerString
= KeyValue
;
156 /* Loop the command line */
157 while (*ServerString
)
159 /* Check for the Entry Point */
160 if ((*ServerString
== ':') && (!EntryPoint
))
162 /* Found it. Add a nullchar and save it */
163 *ServerString
++ = '\0';
164 EntryPoint
= ServerString
;
167 /* Check for the Dll Index */
168 if (*ServerString
++ == ',')
170 /* Convert it to a ULONG */
171 Status
= RtlCharToInteger(ServerString
, 10, &DllIndex
);
173 /* Add a null char if it was valid */
174 if (NT_SUCCESS(Status
)) ServerString
[-1] = '\0';
176 /* We're done here */
181 /* We've got the name, entrypoint and index, load it */
182 return CsrLoadServerDll(KeyValue
, EntryPoint
, DllIndex
);
186 * @name CsrpParseCommandLine
188 * The CsrpParseCommandLine routine parses the CSRSS command-line in the
189 * registry and performs operations for each entry found.
191 * @param ArgumentCount
192 * Number of arguments on the command line.
195 * Array of arguments.
197 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
205 CsrpParseCommandLine(IN ULONG ArgumentCount
,
206 IN PCHAR Arguments
[])
209 PCHAR ParameterName
= NULL
;
210 PCHAR ParameterValue
= NULL
;
213 /* Set the Defaults */
214 CsrTotalPerProcessDataLength
= 0;
215 CsrObjectDirectory
= 0;
216 CsrMaxApiRequestThreads
= 16;
218 /* Save our Session ID, and create a Directory for it */
219 SessionId
= NtCurrentPeb()->SessionId
;
220 Status
= CsrCreateSessionObjectDirectory(SessionId
);
221 if (NT_SUCCESS(Status
))
223 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
226 /* It's not fatal if the SID is 0 */
227 if (SessionId
!= 0) return Status
;
230 /* Loop through every argument */
231 for (i
= 1; i
< ArgumentCount
; i
++)
233 /* Split Name and Value */
234 ParameterName
= Arguments
[i
];
235 ParameterValue
= strchr(ParameterName
, L
'=');
236 *ParameterValue
++ = '\0';
237 DPRINT("Name=%S, Value=%S\n", ParameterName
, ParameterValue
);
239 /* Check for Object Directory */
240 if (!_stricmp(ParameterName
, "ObjectDirectory"))
242 CsrCreateObjectDirectory(ParameterValue
);
244 else if(!_stricmp(ParameterName
, "SubSystemType"))
247 Status
= STATUS_SUCCESS
;
249 else if (!_stricmp(ParameterName
, "MaxRequestThreads"))
251 Status
= RtlCharToInteger(ParameterValue
,
253 &CsrMaxApiRequestThreads
);
255 else if (!_stricmp(ParameterName
, "RequestThreads"))
258 Status
= STATUS_SUCCESS
;
260 else if (!_stricmp(ParameterName
, "ProfileControl"))
262 CsrProfileControl
= (!_stricmp(ParameterValue
, "On")) ? TRUE
: FALSE
;
264 else if (!_stricmp(ParameterName
, "SharedSection"))
266 /* Craete the Section */
267 Status
= CsrSrvCreateSharedSection(ParameterValue
);
270 Status
= CsrLoadServerDll("CSRSS", NULL
, CSR_SRV_SERVER
);
272 else if (!_stricmp(ParameterName
, "ServerDLL"))
274 /* Parse the Command-Line and load this DLL */
275 Status
= CsrLoadServerDllFromCommandLine(ParameterValue
);
277 else if (!_stricmp(ParameterName
, "Windows"))
280 Status
= STATUS_SUCCESS
;
284 /* Invalid parameter on the command line */
285 Status
= STATUS_INVALID_PARAMETER
;
294 * @name CsrCreateObjectDirectory
296 * The CsrCreateObjectDirectory creates the Object Directory on the CSRSS
297 * command-line from the registry.
299 * @param ObjectDirectory
300 * Pointer to the name of the Object Directory to create.
302 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
310 CsrCreateObjectDirectory(IN PCHAR ObjectDirectory
)
312 NTSTATUS Status
= STATUS_SUCCESS
;
313 ANSI_STRING TempString
;
314 OBJECT_ATTRIBUTES DirectoryAttributes
;
316 DPRINT("CSRSRV:%s(%s) called\n", __FUNCTION__
, ObjectDirectory
);
318 /* Convert the parameter to our Global Unicode name */
319 RtlInitAnsiString(&TempString
, ObjectDirectory
);
320 Status
= RtlAnsiStringToUnicodeString(&CsrDirectoryName
, &TempString
, TRUE
);
322 /* Initialize the attributes for the Directory */
323 InitializeObjectAttributes(&DirectoryAttributes
,
325 OBJ_PERMANENT
| OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
330 Status
= NtCreateDirectoryObject(&CsrObjectDirectory
,
331 DIRECTORY_ALL_ACCESS
,
332 &DirectoryAttributes
);
333 if (!NT_SUCCESS(Status
))
335 DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
336 __FUNCTION__
, Status
);
339 /* Set the Security */
340 Status
= CsrSetDirectorySecurity(CsrObjectDirectory
);
347 * @name CsrCreateLocalSystemSD
349 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
350 * the local account with PORT_ALL_ACCESS.
352 * @param LocalSystemSd
353 * Pointer to a pointer to the security descriptor to create.
355 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
363 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR
*LocalSystemSd
)
365 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
368 PSECURITY_DESCRIPTOR SecurityDescriptor
;
372 /* Initialize the System SID */
373 RtlAllocateAndInitializeSid(&NtSidAuthority
,
375 SECURITY_LOCAL_SYSTEM_RID
,
385 /* Get the length of the SID */
386 SidLength
= RtlLengthSid(SystemSid
);
388 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
389 SecurityDescriptor
= RtlAllocateHeap(CsrHeap
,
391 SECURITY_DESCRIPTOR_MIN_LENGTH
+
392 sizeof(ACL
) + SidLength
+
393 sizeof(ACCESS_ALLOWED_ACE
));
395 /* Set the pointer to the DACL */
396 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
398 /* Now create the SD itself */
399 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
400 SECURITY_DESCRIPTOR_REVISION
);
401 if (!NT_SUCCESS(Status
))
404 RtlFreeHeap(CsrHeap
, 0, SecurityDescriptor
);
408 /* Create the DACL for it*/
410 sizeof(ACL
) + SidLength
+ sizeof(ACCESS_ALLOWED_ACE
),
414 Status
= RtlAddAccessAllowedAce(Dacl
,
418 if (!NT_SUCCESS(Status
))
421 RtlFreeHeap(CsrHeap
, 0, SecurityDescriptor
);
425 /* Clear the DACL in the SD */
426 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
430 if (!NT_SUCCESS(Status
))
433 RtlFreeHeap(CsrHeap
, 0, SecurityDescriptor
);
437 /* Free the SID and return*/
438 RtlFreeSid(SystemSid
);
439 *LocalSystemSd
= SecurityDescriptor
;
444 * @name CsrGetDosDevicesSd
446 * The CsrGetDosDevicesSd creates a security descriptor for the DOS Devices
449 * @param DosDevicesSd
450 * Pointer to the Security Descriptor to return.
452 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
455 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
456 * regular users may or may not have full access to the directory.
461 CsrGetDosDevicesSd(OUT PSECURITY_DESCRIPTOR DosDevicesSd
)
463 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
464 SID_IDENTIFIER_AUTHORITY CreatorAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
465 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
466 PSID WorldSid
, CreatorSid
, AdminSid
, SystemSid
;
467 UCHAR KeyValueBuffer
[0x40];
468 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
469 UNICODE_STRING KeyName
;
470 ULONG ProtectionMode
= 0;
471 OBJECT_ATTRIBUTES ObjectAttributes
;
473 PACCESS_ALLOWED_ACE Ace
;
476 ULONG ResultLength
, SidLength
;
479 RtlCreateSecurityDescriptor(DosDevicesSd
, SECURITY_DESCRIPTOR_REVISION
);
481 /* Initialize the System SID */
482 RtlAllocateAndInitializeSid(&NtSidAuthority
,
484 SECURITY_LOCAL_SYSTEM_RID
,
494 /* Initialize the World SID */
495 RtlAllocateAndInitializeSid(&WorldAuthority
,
507 /* Initialize the Admin SID */
508 RtlAllocateAndInitializeSid(&NtSidAuthority
,
510 SECURITY_BUILTIN_DOMAIN_RID
,
511 DOMAIN_ALIAS_RID_ADMINS
,
520 /* Initialize the Creator SID */
521 RtlAllocateAndInitializeSid(&CreatorAuthority
,
523 SECURITY_CREATOR_OWNER_RID
,
533 /* Open the Session Manager Key */
534 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
535 InitializeObjectAttributes(&ObjectAttributes
,
537 OBJ_CASE_INSENSITIVE
,
540 if (NT_SUCCESS(Status
= NtOpenKey(&hKey
,
544 /* Read the ProtectionMode. See http://support.microsoft.com/kb/q218473/ */
545 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
546 Status
= NtQueryValueKey(hKey
,
548 KeyValuePartialInformation
,
550 sizeof(KeyValueBuffer
),
553 /* Make sure it's what we expect it to be */
554 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
555 if ((KeyValuePartialInfo
->Type
== REG_DWORD
) &&
556 (*(PULONG
)KeyValuePartialInfo
->Data
!= 0))
558 /* Save the Protection Mode */
559 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
562 /* Close the handle */
566 /* Check the Protection Mode */
567 if (ProtectionMode
& 3)
569 /* Calculate SID Lengths */
570 SidLength
= RtlLengthSid(CreatorSid
) + RtlLengthSid(SystemSid
) +
571 RtlLengthSid(AdminSid
);
573 /* Allocate memory for the DACL */
574 Dacl
= RtlAllocateHeap(CsrHeap
,
576 sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
580 Status
= RtlCreateAcl(Dacl
,
581 sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
585 /* Give full access to the System */
586 Status
= RtlAddAccessAllowedAce(Dacl
,
591 /* Get the ACE back */
592 Status
= RtlGetAce(Dacl
, 0, (PVOID
*)&Ace
);
594 /* Add some flags to it for the Admin SID */
595 Ace
->Header
.AceFlags
|= (OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
);
597 /* Add the ACE to the Admin SID */
598 Status
= RtlAddAccessAllowedAce(Dacl
,
603 /* Get the ACE back */
604 Status
= RtlGetAce(Dacl
, 1, (PVOID
*)&Ace
);
606 /* Add some flags to it for the Creator SID */
607 Ace
->Header
.AceFlags
|= (OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
);
609 /* Add the ACE to the Admin SID */
610 Status
= RtlAddAccessAllowedAce(Dacl
,
615 /* Get the ACE back */
616 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
618 /* Add some flags to it for the SD */
619 Ace
->Header
.AceFlags
|= (OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
|
622 /* Set this DACL with the SD */
623 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
,
630 /* Calculate SID Lengths */
631 SidLength
= RtlLengthSid(WorldSid
) + RtlLengthSid(SystemSid
);
633 /* Allocate memory for the DACL */
634 Dacl
= RtlAllocateHeap(CsrHeap
,
636 sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
640 Status
= RtlCreateAcl(Dacl
,
641 sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
645 /* Give RWE access to the World */
646 Status
= RtlAddAccessAllowedAce(Dacl
,
648 GENERIC_READ
| GENERIC_WRITE
|
652 /* Give full access to the System */
653 Status
= RtlAddAccessAllowedAce(Dacl
,
658 /* Give full access to the World */
659 Status
= RtlAddAccessAllowedAce(Dacl
,
664 /* Get the ACE back */
665 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
667 /* Add some flags to it for the SD */
668 Ace
->Header
.AceFlags
|= (OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
|
671 /* Set this DACL with the SD */
672 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
,
678 /* FIXME: failure cases! Fail: */
679 /* Free the memory */
680 RtlFreeHeap(CsrHeap
, 0, Dacl
);
682 /* FIXME: semi-failure cases! Quickie: */
684 RtlFreeSid(SystemSid
);
685 RtlFreeSid(WorldSid
);
686 RtlFreeSid(AdminSid
);
687 RtlFreeSid(CreatorSid
);
694 * @name CsrFreeDosDevicesSd
696 * The CsrFreeDosDevicesSd frees the security descriptor that was created
697 * by CsrGetDosDevicesSd
699 * @param DosDevicesSd
700 * Pointer to the security descriptor to free.
709 CsrFreeDosDevicesSd(IN PSECURITY_DESCRIPTOR DosDevicesSd
)
712 BOOLEAN Present
, Default
;
715 /* Get the DACL corresponding to this SD */
716 Status
= RtlGetDaclSecurityDescriptor(DosDevicesSd
,
722 if (NT_SUCCESS(Status
) && Dacl
) RtlFreeHeap(CsrHeap
, 0, Dacl
);
726 * @name CsrCreateSessionObjectDirectory
728 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
729 * Session and Dos Devices directories for the specified session.
732 * Session ID for which to create the directories.
734 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
742 CsrCreateSessionObjectDirectory(IN ULONG Session
)
744 WCHAR SessionBuffer
[512];
745 WCHAR BnoBuffer
[512];
746 UNICODE_STRING SessionString
;
747 UNICODE_STRING BnoString
;
748 OBJECT_ATTRIBUTES ObjectAttributes
;
750 SECURITY_DESCRIPTOR DosDevicesSd
;
753 /* Generate the Session BNOLINKS Directory */
754 swprintf(SessionBuffer
, L
"%ws\\BNOLINKS", SESSION_ROOT
);
755 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
757 /* Initialize the attributes for the Directory */
758 InitializeObjectAttributes(&ObjectAttributes
,
760 OBJ_PERMANENT
| OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
765 Status
= NtCreateDirectoryObject(&BNOLinksDirectory
,
766 DIRECTORY_ALL_ACCESS
,
768 if (!NT_SUCCESS(Status
))
770 DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
771 __FUNCTION__
, Status
);
775 /* Now add the Session ID */
776 swprintf(SessionBuffer
, L
"%ld", Session
);
777 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
779 /* Check if this is the first Session */
782 /* Not the first, so the name will be slighly more complex */
783 swprintf(BnoBuffer
, L
"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT
, Session
);
787 /* Use the direct name */
788 RtlCopyMemory(BnoBuffer
, L
"\\BaseNamedObjects", 36);
791 /* Create the Unicode String for the BNO SymLink */
792 RtlInitUnicodeString(&BnoString
, BnoBuffer
);
794 /* Initialize the attributes for the SymLink */
795 InitializeObjectAttributes(&ObjectAttributes
,
797 OBJ_PERMANENT
| OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
802 Status
= NtCreateSymbolicLinkObject(&BnoHandle
,
803 SYMBOLIC_LINK_ALL_ACCESS
,
806 if (!NT_SUCCESS(Status
))
808 DPRINT1("CSRSRV:%s: fatal: NtCreateSymbolicLinkObject failed (Status=0x%08lx)\n",
809 __FUNCTION__
, Status
);
813 /* Create the \DosDevices Security Descriptor */
814 CsrGetDosDevicesSd(&DosDevicesSd
);
816 /* Now create a directory for this session */
817 swprintf(SessionBuffer
, L
"%ws\\%ld", SESSION_ROOT
, Session
);
818 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
820 /* Initialize the attributes for the Directory */
821 InitializeObjectAttributes(&ObjectAttributes
,
823 OBJ_PERMANENT
| OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
828 Status
= NtCreateDirectoryObject(&SessionObjectDirectory
,
829 DIRECTORY_ALL_ACCESS
,
831 if (!NT_SUCCESS(Status
))
833 DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
834 __FUNCTION__
, Status
);
835 /* Release the Security Descriptor */
836 CsrFreeDosDevicesSd(&DosDevicesSd
);
840 /* Next, create a directory for this session's DOS Devices */
841 /* Now create a directory for this session */
842 RtlInitUnicodeString(&SessionString
, L
"DosDevices");
844 /* Initialize the attributes for the Directory */
845 InitializeObjectAttributes(&ObjectAttributes
,
847 OBJ_PERMANENT
| OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
852 Status
= NtCreateDirectoryObject(&DosDevicesDirectory
,
853 DIRECTORY_ALL_ACCESS
,
855 if (!NT_SUCCESS(Status
))
857 DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
858 __FUNCTION__
, Status
);
861 /* Release the Security Descriptor */
862 CsrFreeDosDevicesSd(&DosDevicesSd
);
869 * @name CsrSetProcessSecurity
871 * The CsrSetProcessSecurity routine protects access to the CSRSS process
872 * from unauthorized tampering.
876 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
884 CsrSetProcessSecurity(VOID
)
889 PTOKEN_USER TokenUserInformation
;
890 PSECURITY_DESCRIPTOR SecurityDescriptor
;
894 Status
= NtOpenProcessToken(NtCurrentProcess(),
897 if (!NT_SUCCESS(Status
)) return Status
;
899 /* Get the Token User Length */
900 NtQueryInformationToken(hToken
,
906 /* Allocate space for it */
907 TokenUserInformation
= RtlAllocateHeap(CsrHeap
,
911 /* Now query the data */
912 Status
= NtQueryInformationToken(hToken
,
914 TokenUserInformation
,
918 /* Close the handle */
921 /* Make sure that we got the data */
922 if (!NT_SUCCESS(Status
))
925 RtlFreeHeap(CsrHeap
, 0, TokenUserInformation
);
929 /* Now check the SID Length */
930 ReturnLength
= RtlLengthSid(TokenUserInformation
->User
.Sid
);
932 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
933 SecurityDescriptor
= RtlAllocateHeap(CsrHeap
,
935 SECURITY_DESCRIPTOR_MIN_LENGTH
+
936 sizeof(ACL
) + ReturnLength
+
937 sizeof(ACCESS_ALLOWED_ACE
));
939 /* Set the pointer to the DACL */
940 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
942 /* Now create the SD itself */
943 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
944 SECURITY_DESCRIPTOR_REVISION
);
945 if (!NT_SUCCESS(Status
))
948 RtlFreeHeap(CsrHeap
, 0, SecurityDescriptor
);
949 RtlFreeHeap(CsrHeap
, 0, TokenUserInformation
);
953 /* Create the DACL for it*/
955 sizeof(ACL
) + ReturnLength
+ sizeof(ACCESS_ALLOWED_ACE
),
959 Status
= RtlAddAccessAllowedAce(Dacl
,
961 PROCESS_VM_READ
| PROCESS_VM_WRITE
|
962 PROCESS_VM_OPERATION
| PROCESS_DUP_HANDLE
|
963 PROCESS_TERMINATE
| PROCESS_SUSPEND_RESUME
|
964 PROCESS_QUERY_INFORMATION
| READ_CONTROL
,
965 TokenUserInformation
->User
.Sid
);
966 if (!NT_SUCCESS(Status
))
969 RtlFreeHeap(CsrHeap
, 0, SecurityDescriptor
);
970 RtlFreeHeap(CsrHeap
, 0, TokenUserInformation
);
974 /* Clear the DACL in the SD */
975 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
979 if (!NT_SUCCESS(Status
))
982 RtlFreeHeap(CsrHeap
, 0, SecurityDescriptor
);
983 RtlFreeHeap(CsrHeap
, 0, TokenUserInformation
);
987 /* Write the SD into the Process */
988 Status
= NtSetSecurityObject(NtCurrentProcess(),
989 DACL_SECURITY_INFORMATION
,
992 /* Free the memory and return */
993 RtlFreeHeap(CsrHeap
, 0, SecurityDescriptor
);
994 RtlFreeHeap(CsrHeap
, 0, TokenUserInformation
);
999 * @name CsrSetDirectorySecurity
1001 * The CsrSetDirectorySecurity routine sets the security descriptor for the
1002 * specified Object Directory.
1004 * @param ObjectDirectory
1005 * Handle fo the Object Directory to protect.
1007 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
1015 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory
)
1017 /* FIXME: Implement */
1018 return STATUS_SUCCESS
;
1021 /* PUBLIC FUNCTIONS **********************************************************/
1024 * @name CsrServerInitialization
1027 * The CsrServerInitialization routine is the native (not Server) entrypoint
1028 * of this Server DLL. It serves as the entrypoint for csrss.
1030 * @param ArgumentCount
1031 * Number of arguments on the command line.
1034 * Array of arguments from the command line.
1036 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
1044 CsrServerInitialization(ULONG ArgumentCount
,
1047 NTSTATUS Status
= STATUS_SUCCESS
;
1050 PCSR_SERVER_DLL ServerDll
;
1052 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
1054 /* Create the Init Event */
1055 Status
= NtCreateEvent(&CsrInitializationEvent
,
1058 SynchronizationEvent
,
1061 /* Cache System Basic Information so we don't always request it */
1062 Status
= NtQuerySystemInformation(SystemBasicInformation
,
1064 sizeof(SYSTEM_BASIC_INFORMATION
),
1068 CsrHeap
= RtlGetProcessHeap();
1070 /* Set our Security Descriptor to protect the process */
1071 CsrSetProcessSecurity();
1073 /* Set up Session Support */
1074 Status
= CsrInitializeNtSessions();
1075 if(!NT_SUCCESS(Status
))
1077 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
1078 __FUNCTION__
, Status
);
1082 /* Set up Process Support */
1083 Status
= CsrInitializeProcesses();
1084 if(!NT_SUCCESS(Status
))
1086 DPRINT1("CSRSRV:%s: CsrInitializeProcesses failed (Status=%08lx)\n",
1087 __FUNCTION__
, Status
);
1091 /* Parse the command line */
1092 CsrpParseCommandLine(ArgumentCount
, Arguments
);
1094 /* All Server DLLs are now loaded, allocate a heap for the Root Process */
1095 ProcessData
= RtlAllocateHeap(CsrHeap
,
1097 CsrTotalPerProcessDataLength
);
1100 * Our Root Process was never officially initalized, so write the data
1101 * for each Server DLL manually.
1103 for(i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
1105 /* Get the current Server */
1106 ServerDll
= CsrLoadedServerDll
[i
];
1108 /* Is it loaded, and does it have per process data? */
1109 if (ServerDll
&& ServerDll
->SizeOfProcessData
)
1111 /* It does, give it part of our allocated heap */
1112 CsrRootProcess
->ServerData
[i
] = ProcessData
;
1114 /* Move to the next heap position */
1115 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
1116 ServerDll
->SizeOfProcessData
);
1120 /* Nothing for this Server DLL */
1121 CsrRootProcess
->ServerData
[i
] = NULL
;
1125 /* Now initialize the Root Process manually as well */
1126 for(i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
1128 /* Get the current Server */
1129 ServerDll
= CsrLoadedServerDll
[i
];
1131 /* Is it loaded, and does it a callback for new processes? */
1132 if (ServerDll
&& ServerDll
->NewProcessCallback
)
1134 /* Call the callback */
1135 (*ServerDll
->NewProcessCallback
)(NULL
, CsrRootProcess
);
1139 /* Now initialize our API Port */
1140 Status
= CsrApiPortInitialize();
1141 if(!NT_SUCCESS(Status
))
1143 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n",
1144 __FUNCTION__
, Status
);
1148 /* Initialize the API Port for SM communication */
1149 Status
= CsrSbApiPortInitialize();
1150 if(!NT_SUCCESS(Status
))
1152 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n",
1153 __FUNCTION__
, Status
);
1157 /* We're all set! Connect to SM! */
1158 Status
= SmConnectToSm(&CsrSbApiPortName
,
1160 IMAGE_SUBSYSTEM_WINDOWS_GUI
,
1162 if(!NT_SUCCESS(Status
))
1164 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n",
1165 __FUNCTION__
, Status
);
1169 /* Finito! Signal the event */
1170 NtSetEvent(CsrInitializationEvent
, NULL
);
1171 NtClose(CsrInitializationEvent
);
1173 /* Have us handle Hard Errors */
1174 NtSetDefaultHardErrorPort(CsrApiPort
);
1181 * @name CsrPopulateDosDevices
1182 * @implemented NT5.1
1184 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1185 * to populate the Dos Devices Object Directory for the session.
1196 CsrPopulateDosDevices(VOID
)
1199 PROCESS_DEVICEMAP_INFORMATION OldDeviceMap
;
1200 PROCESS_DEVICEMAP_INFORMATION NewDeviceMap
;
1202 /* Query the Device Map */
1203 Status
= NtQueryInformationProcess(NtCurrentProcess(),
1205 &OldDeviceMap
.Query
,
1206 sizeof(PROCESS_DEVICEMAP_INFORMATION
),
1208 if (!NT_SUCCESS(Status
)) return;
1210 /* Set the new one */
1211 NewDeviceMap
.Set
.DirectoryHandle
= DosDevicesDirectory
;
1212 Status
= NtSetInformationProcess(NtCurrentProcess(),
1216 if (!NT_SUCCESS(Status
)) return;
1218 /* Populate the Directory */
1219 CsrPopulateDosDevicesDirectory(DosDevicesDirectory
, &OldDeviceMap
);
1224 DllMain(HANDLE hDll
,
1228 /* We don't do much */