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
= 0xFFFFFFFF; // 0;
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 **********************************************************/
41 /* === INIT ROUTINES === */
44 * @name CsrSetProcessSecurity
46 * The CsrSetProcessSecurity routine protects access to the CSRSS process
47 * from unauthorized tampering.
51 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
59 CsrSetProcessSecurity(VOID
)
62 HANDLE hToken
, hProcess
= NtCurrentProcess();
64 PTOKEN_USER TokenInfo
= NULL
;
65 PSECURITY_DESCRIPTOR ProcSd
= NULL
;
70 Status
= NtOpenProcessToken(hProcess
, TOKEN_QUERY
, &hToken
);
71 if (!NT_SUCCESS(Status
)) goto Quickie
;
73 /* Get the Token User Length */
74 NtQueryInformationToken(hToken
, TokenUser
, NULL
, 0, &Length
);
76 /* Allocate space for it */
77 TokenInfo
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Length
);
80 Status
= STATUS_NO_MEMORY
;
84 /* Now query the data */
85 Status
= NtQueryInformationToken(hToken
, TokenUser
, TokenInfo
, Length
, &Length
);
87 if (!NT_SUCCESS(Status
)) goto Quickie
;
89 /* Now check the SID Length */
90 UserSid
= TokenInfo
->User
.Sid
;
91 Length
= RtlLengthSid(UserSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
93 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
94 ProcSd
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
97 Status
= STATUS_NO_MEMORY
;
101 /* Set the pointer to the DACL */
102 Dacl
= (PACL
)((ULONG_PTR
)ProcSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
104 /* Now create the SD itself */
105 Status
= RtlCreateSecurityDescriptor(ProcSd
, SECURITY_DESCRIPTOR_REVISION
);
106 if (!NT_SUCCESS(Status
))
108 DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status
);
112 /* Create the DACL for it*/
113 Status
= RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
114 if (!NT_SUCCESS(Status
))
116 DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status
);
121 Status
= RtlAddAccessAllowedAce(Dacl
,
123 PROCESS_VM_READ
| PROCESS_VM_WRITE
|
124 PROCESS_VM_OPERATION
| PROCESS_DUP_HANDLE
|
125 PROCESS_TERMINATE
| PROCESS_SUSPEND_RESUME
|
126 PROCESS_QUERY_INFORMATION
| READ_CONTROL
,
128 if (!NT_SUCCESS(Status
))
130 DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status
);
134 /* Clear the DACL in the SD */
135 Status
= RtlSetDaclSecurityDescriptor(ProcSd
, TRUE
, Dacl
, FALSE
);
136 if (!NT_SUCCESS(Status
))
138 DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status
);
142 /* Write the SD into the Process */
143 Status
= NtSetSecurityObject(hProcess
, DACL_SECURITY_INFORMATION
, ProcSd
);
144 if (!NT_SUCCESS(Status
))
146 DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status
);
150 /* Free the memory and return */
152 if (ProcSd
) RtlFreeHeap(CsrHeap
, 0, ProcSd
);
153 RtlFreeHeap(CsrHeap
, 0, TokenInfo
);
158 * @name CsrSetDirectorySecurity
160 * The CsrSetDirectorySecurity routine sets the security descriptor for the
161 * specified Object Directory.
163 * @param ObjectDirectory
164 * Handle fo the Object Directory to protect.
166 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
174 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory
)
176 /* FIXME: Implement */
177 return STATUS_SUCCESS
;
181 * @name GetDosDevicesProtection
183 * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
186 * @param DosDevicesSd
187 * Pointer to the Security Descriptor to return.
189 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
192 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
193 * regular users may or may not have full access to the directory.
198 GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd
)
200 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
201 SID_IDENTIFIER_AUTHORITY CreatorAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
202 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
203 PSID WorldSid
, CreatorSid
, AdminSid
, SystemSid
;
204 UCHAR KeyValueBuffer
[0x40];
205 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
206 UNICODE_STRING KeyName
;
207 ULONG ProtectionMode
= 0;
208 OBJECT_ATTRIBUTES ObjectAttributes
;
210 PACCESS_ALLOWED_ACE Ace
;
213 ULONG ResultLength
, SidLength
, AclLength
;
216 Status
= RtlCreateSecurityDescriptor(DosDevicesSd
, SECURITY_DESCRIPTOR_REVISION
);
217 ASSERT(NT_SUCCESS(Status
));
219 /* Initialize the System SID */
220 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
221 SECURITY_LOCAL_SYSTEM_RID
,
224 ASSERT(NT_SUCCESS(Status
));
226 /* Initialize the World SID */
227 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
, 1,
231 ASSERT(NT_SUCCESS(Status
));
233 /* Initialize the Admin SID */
234 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 2,
235 SECURITY_BUILTIN_DOMAIN_RID
,
236 DOMAIN_ALIAS_RID_ADMINS
,
239 ASSERT(NT_SUCCESS(Status
));
241 /* Initialize the Creator SID */
242 Status
= RtlAllocateAndInitializeSid(&CreatorAuthority
, 1,
243 SECURITY_CREATOR_OWNER_RID
,
246 ASSERT(NT_SUCCESS(Status
));
248 /* Open the Session Manager Key */
249 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
250 InitializeObjectAttributes(&ObjectAttributes
,
252 OBJ_CASE_INSENSITIVE
,
255 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
256 if (NT_SUCCESS(Status
))
258 /* Read the key value */
259 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
260 Status
= NtQueryValueKey(hKey
,
262 KeyValuePartialInformation
,
264 sizeof(KeyValueBuffer
),
267 /* Make sure it's what we expect it to be */
268 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
269 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
270 (*(PULONG
)KeyValuePartialInfo
->Data
))
272 /* Save the Protection Mode */
273 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
276 /* Close the handle */
280 /* Check the Protection Mode */
281 if (ProtectionMode
& 3)
283 /* Calculate SID Lengths */
284 SidLength
= RtlLengthSid(CreatorSid
) + RtlLengthSid(SystemSid
) +
285 RtlLengthSid(AdminSid
);
286 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
288 /* Allocate memory for the DACL */
289 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
290 ASSERT(Dacl
!= NULL
);
292 /* Build the ACL and add 3 ACEs */
293 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
294 ASSERT(NT_SUCCESS(Status
));
295 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
296 ASSERT(NT_SUCCESS(Status
));
297 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, AdminSid
);
298 ASSERT(NT_SUCCESS(Status
));
299 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, CreatorSid
);
300 ASSERT(NT_SUCCESS(Status
));
302 /* Edit the ACEs to make them inheritable */
303 Status
= RtlGetAce(Dacl
, 0, (PVOID
*)&Ace
);
304 ASSERT(NT_SUCCESS(Status
));
305 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
306 Status
= RtlGetAce(Dacl
, 1, (PVOID
*)&Ace
);
307 ASSERT(NT_SUCCESS(Status
));
308 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
309 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
310 ASSERT(NT_SUCCESS(Status
));
311 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
313 /* Set this DACL with the SD */
314 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
315 ASSERT(NT_SUCCESS(Status
));
320 /* Calculate SID Lengths */
321 SidLength
= RtlLengthSid(WorldSid
) + RtlLengthSid(SystemSid
);
322 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
324 /* Allocate memory for the DACL */
325 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
326 ASSERT(Dacl
!= NULL
);
328 /* Build the ACL and add 3 ACEs */
329 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
330 ASSERT(NT_SUCCESS(Status
));
331 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
, WorldSid
);
332 ASSERT(NT_SUCCESS(Status
));
333 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
334 ASSERT(NT_SUCCESS(Status
));
335 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, WorldSid
);
336 ASSERT(NT_SUCCESS(Status
));
338 /* Edit the last ACE to make it inheritable */
339 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
340 ASSERT(NT_SUCCESS(Status
));
341 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
343 /* Set this DACL with the SD */
344 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
345 ASSERT(NT_SUCCESS(Status
));
349 /* FIXME: failure cases! Fail: */
350 /* Free the memory */
351 RtlFreeHeap(CsrHeap
, 0, Dacl
);
353 /* FIXME: semi-failure cases! Quickie: */
356 RtlFreeSid(SystemSid
);
357 RtlFreeSid(WorldSid
);
358 RtlFreeSid(AdminSid
);
359 RtlFreeSid(CreatorSid
);
366 * @name FreeDosDevicesProtection
368 * The FreeDosDevicesProtection frees the security descriptor that was created
369 * by GetDosDevicesProtection
371 * @param DosDevicesSd
372 * Pointer to the security descriptor to free.
381 FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd
)
384 BOOLEAN Present
, Default
;
387 /* Get the DACL corresponding to this SD */
388 Status
= RtlGetDaclSecurityDescriptor(DosDevicesSd
, &Present
, &Dacl
, &Default
);
389 ASSERT(NT_SUCCESS(Status
));
391 ASSERT(Dacl
!= NULL
);
394 if ((NT_SUCCESS(Status
)) && (Dacl
)) RtlFreeHeap(CsrHeap
, 0, Dacl
);
398 * @name CsrCreateSessionObjectDirectory
400 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
401 * Session and Dos Devices directories for the specified session.
404 * Session ID for which to create the directories.
406 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
414 CsrCreateSessionObjectDirectory(IN ULONG Session
)
416 WCHAR SessionBuffer
[512], BnoBuffer
[512];
417 UNICODE_STRING SessionString
, BnoString
;
418 OBJECT_ATTRIBUTES ObjectAttributes
;
420 SECURITY_DESCRIPTOR DosDevicesSd
;
423 /* Generate the Session BNOLINKS Directory name */
424 swprintf(SessionBuffer
, L
"%ws\\BNOLINKS", SESSION_ROOT
);
425 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
428 InitializeObjectAttributes(&ObjectAttributes
,
430 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
433 Status
= NtCreateDirectoryObject(&BNOLinksDirectory
,
434 DIRECTORY_ALL_ACCESS
,
436 if (!NT_SUCCESS(Status
))
438 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
439 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
443 /* Now add the Session ID */
444 swprintf(SessionBuffer
, L
"%ld", Session
);
445 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
447 /* Check if this is the first Session */
450 /* Not the first, so the name will be slighly more complex */
451 swprintf(BnoBuffer
, L
"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT
, Session
);
452 RtlInitUnicodeString(&BnoString
, BnoBuffer
);
456 /* Use the direct name */
457 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
460 /* Create the symlink */
461 InitializeObjectAttributes(&ObjectAttributes
,
463 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
466 Status
= NtCreateSymbolicLinkObject(&BnoHandle
,
467 SYMBOLIC_LINK_ALL_ACCESS
,
470 if (!NT_SUCCESS(Status
))
472 DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
473 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
477 /* Create the \DosDevices Security Descriptor */
478 Status
= GetDosDevicesProtection(&DosDevicesSd
);
479 if (!NT_SUCCESS(Status
)) return Status
;
481 /* Now create a directory for this session */
482 swprintf(SessionBuffer
, L
"%ws\\%ld", SESSION_ROOT
, Session
);
483 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
485 /* Create the directory */
486 InitializeObjectAttributes(&ObjectAttributes
,
488 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
491 Status
= NtCreateDirectoryObject(&SessionObjectDirectory
,
492 DIRECTORY_ALL_ACCESS
,
494 if (!NT_SUCCESS(Status
))
496 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
497 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
498 FreeDosDevicesProtection(&DosDevicesSd
);
502 /* Next, create a directory for this session's DOS Devices */
503 RtlInitUnicodeString(&SessionString
, L
"DosDevices");
504 InitializeObjectAttributes(&ObjectAttributes
,
506 OBJ_CASE_INSENSITIVE
,
507 SessionObjectDirectory
,
509 Status
= NtCreateDirectoryObject(&DosDevicesDirectory
,
510 DIRECTORY_ALL_ACCESS
,
512 if (!NT_SUCCESS(Status
))
514 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
515 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
518 /* Release the Security Descriptor */
519 FreeDosDevicesProtection(&DosDevicesSd
);
526 * @name CsrParseServerCommandLine
528 * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
529 * registry and performs operations for each entry found.
531 * @param ArgumentCount
532 * Number of arguments on the command line.
535 * Array of arguments.
537 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
545 CsrParseServerCommandLine(IN ULONG ArgumentCount
,
546 IN PCHAR Arguments
[])
549 PCHAR ParameterName
= NULL
, ParameterValue
= NULL
, EntryPoint
, ServerString
;
551 ANSI_STRING AnsiString
;
552 OBJECT_ATTRIBUTES ObjectAttributes
;
554 /* Set the Defaults */
555 CsrTotalPerProcessDataLength
= 0;
556 CsrObjectDirectory
= NULL
;
557 CsrMaxApiRequestThreads
= 16;
559 /* Save our Session ID, and create a Directory for it */
560 SessionId
= NtCurrentPeb()->SessionId
;
561 Status
= CsrCreateSessionObjectDirectory(SessionId
);
562 if (!NT_SUCCESS(Status
))
564 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
567 /* It's not fatal if the session ID isn't zero */
568 if (SessionId
) return Status
;
569 ASSERT(NT_SUCCESS(Status
));
572 /* Loop through every argument */
573 for (i
= 1; i
< ArgumentCount
; i
++)
575 /* Split Name and Value */
576 ParameterName
= Arguments
[i
];
577 ParameterValue
= NULL
;
578 ParameterValue
= strchr(ParameterName
, '=');
579 if (ParameterValue
) *ParameterValue
++ = ANSI_NULL
;
580 DPRINT1("Name=%s, Value=%s\n", ParameterName
, ParameterValue
);
582 /* Check for Object Directory */
583 if (_stricmp(ParameterName
, "ObjectDirectory") == 0)
585 /* Check if a session ID is specified */
588 DPRINT1("Sessions not yet implemented\n");
592 /* Initialize the directory name */
593 RtlInitAnsiString(&AnsiString
, ParameterValue
);
594 Status
= RtlAnsiStringToUnicodeString(&CsrDirectoryName
,
597 ASSERT(NT_SUCCESS(Status
) || SessionId
!= 0);
598 if (!NT_SUCCESS(Status
)) return Status
;
601 InitializeObjectAttributes(&ObjectAttributes
,
603 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
606 Status
= NtCreateDirectoryObject(&CsrObjectDirectory
,
607 DIRECTORY_ALL_ACCESS
,
609 if (!NT_SUCCESS(Status
)) return Status
;
612 Status
= CsrSetDirectorySecurity(CsrObjectDirectory
);
613 if (!NT_SUCCESS(Status
)) return Status
;
615 else if (_stricmp(ParameterName
, "SubSystemType") == 0)
619 else if (_stricmp(ParameterName
, "MaxRequestThreads") == 0)
621 Status
= RtlCharToInteger(ParameterValue
,
623 &CsrMaxApiRequestThreads
);
625 else if (_stricmp(ParameterName
, "RequestThreads") == 0)
628 Status
= STATUS_SUCCESS
;
630 else if (_stricmp(ParameterName
, "ProfileControl") == 0)
634 else if (_stricmp(ParameterName
, "SharedSection") == 0)
636 /* Create the Section */
637 Status
= CsrSrvCreateSharedSection(ParameterValue
);
638 if (!NT_SUCCESS(Status
))
640 DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
641 ParameterName
, ParameterValue
, Status
);
646 Status
= CsrLoadServerDll("CSRSS" /* "CSRSRV" */, NULL
, CSRSRV_SERVERDLL_INDEX
);
648 else if (_stricmp(ParameterName
, "ServerDll") == 0)
650 /* Loop the command line */
652 Status
= STATUS_INVALID_PARAMETER
;
653 ServerString
= ParameterValue
;
654 while (*ServerString
)
656 /* Check for the Entry Point */
657 if ((*ServerString
== ':') && (!EntryPoint
))
659 /* Found it. Add a nullchar and save it */
660 *ServerString
++ = ANSI_NULL
;
661 EntryPoint
= ServerString
;
664 /* Check for the Dll Index */
665 if (*ServerString
++ == ',') break;
668 /* Did we find something to load? */
671 DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
672 ParameterValue
, Status
);
676 /* Convert it to a ULONG */
677 Status
= RtlCharToInteger(ServerString
, 10, &DllIndex
);
679 /* Add a null char if it was valid */
680 if (NT_SUCCESS(Status
)) ServerString
[-1] = ANSI_NULL
;
683 if (CsrDebug
& 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue
, EntryPoint
);
684 Status
= CsrLoadServerDll(ParameterValue
, EntryPoint
, DllIndex
);
685 if (!NT_SUCCESS(Status
))
687 DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
688 ParameterValue
, Status
);
692 else if (_stricmp(ParameterName
, "Windows") == 0)
695 // Check whether we want to start in pure GUI or pure CLI.
699 /* Invalid parameter on the command line */
700 Status
= STATUS_INVALID_PARAMETER
;
709 * @name CsrInitCsrRootProcess
711 * The CsrInitCsrRootProcess routine further initializes the CSR Root Process
712 * created by CsrInitializeProcessStructure, by allocating and initializing
713 * per-process data for each Server DLL.
717 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
725 CsrInitCsrRootProcess(VOID
)
728 PCSR_SERVER_DLL ServerDll
;
731 /* All Server DLLs are now loaded, allocate a heap for the Root Process */
732 ProcessData
= RtlAllocateHeap(CsrHeap
,
734 CsrTotalPerProcessDataLength
);
737 DPRINT1("CSRSRV:%s: RtlAllocateHeap failed (Status=%08lx)\n",
738 __FUNCTION__
, STATUS_NO_MEMORY
);
739 return STATUS_NO_MEMORY
;
743 * Our Root Process was never officially initalized,
744 * so write the data for each Server DLL manually.
748 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
750 /* Get the current Server */
751 ServerDll
= CsrLoadedServerDll
[i
];
753 /* Is it loaded, and does it have per process data? */
754 if (ServerDll
&& ServerDll
->SizeOfProcessData
)
756 /* It does, give it part of our allocated heap */
757 CsrRootProcess
->ServerData
[i
] = ProcessData
;
759 /* Move to the next heap position */
760 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
761 ServerDll
->SizeOfProcessData
);
765 /* Nothing for this Server DLL */
766 CsrRootProcess
->ServerData
[i
] = NULL
;
770 /* Now initialize the Root Process manually as well */
771 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
773 /* Get the current Server */
774 ServerDll
= CsrLoadedServerDll
[i
];
776 /* Is it loaded, and does it a callback for new processes? */
777 if (ServerDll
&& ServerDll
->NewProcessCallback
)
779 /* Call the callback */
780 DPRINT1("Call NewProcessCallback(NULL, 0x%p) called\n", CsrRootProcess
);
781 ServerDll
->NewProcessCallback(NULL
, CsrRootProcess
);
785 return STATUS_SUCCESS
;
789 * @name CsrCreateLocalSystemSD
791 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
792 * the local account with PORT_ALL_ACCESS.
794 * @param LocalSystemSd
795 * Pointer to a pointer to the security descriptor to create.
797 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
805 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR
*LocalSystemSd
)
807 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
810 PSECURITY_DESCRIPTOR SystemSd
;
814 /* Initialize the System SID */
815 RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
816 SECURITY_LOCAL_SYSTEM_RID
,
820 /* Get the length of the SID */
821 Length
= RtlLengthSid(SystemSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
823 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
824 SystemSd
= RtlAllocateHeap(CsrHeap
, 0, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
826 /* Set the pointer to the DACL */
827 Dacl
= (PACL
)((ULONG_PTR
)SystemSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
829 /* Now create the SD itself */
830 Status
= RtlCreateSecurityDescriptor(SystemSd
, SECURITY_DESCRIPTOR_REVISION
);
831 if (!NT_SUCCESS(Status
))
834 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
838 /* Create the DACL for it */
839 RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
842 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, PORT_ALL_ACCESS
, SystemSid
);
843 if (!NT_SUCCESS(Status
))
846 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
850 /* Clear the DACL in the SD */
851 Status
= RtlSetDaclSecurityDescriptor(SystemSd
, TRUE
, Dacl
, FALSE
);
852 if (!NT_SUCCESS(Status
))
855 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
859 /* Free the SID and return*/
860 RtlFreeSid(SystemSid
);
861 *LocalSystemSd
= SystemSd
;
866 * @name CsrSbApiPortInitialize
868 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
869 * communications with the Session Manager (SM) and initializes the static
870 * thread that will handle connection requests and APIs.
874 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
882 CsrSbApiPortInitialize(VOID
)
885 PSECURITY_DESCRIPTOR PortSd
;
886 OBJECT_ATTRIBUTES ObjectAttributes
;
888 HANDLE hRequestThread
;
891 /* Calculate how much space we'll need for the Port Name */
892 Size
= CsrDirectoryName
.Length
+ sizeof(SB_PORT_NAME
) + sizeof(WCHAR
);
894 /* Create the buffer for it */
895 CsrSbApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
896 if (!CsrSbApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
898 /* Setup the rest of the empty string */
899 CsrSbApiPortName
.Length
= 0;
900 CsrSbApiPortName
.MaximumLength
= (USHORT
)Size
;
902 /* Now append the full port name */
903 RtlAppendUnicodeStringToString(&CsrSbApiPortName
, &CsrDirectoryName
);
904 RtlAppendUnicodeToString(&CsrSbApiPortName
, UNICODE_PATH_SEP
);
905 RtlAppendUnicodeToString(&CsrSbApiPortName
, SB_PORT_NAME
);
906 if (CsrDebug
& 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName
);
908 /* Create Security Descriptor for this Port */
909 Status
= CsrCreateLocalSystemSD(&PortSd
);
910 if (!NT_SUCCESS(Status
)) return Status
;
912 /* Initialize the Attributes */
913 InitializeObjectAttributes(&ObjectAttributes
,
919 /* Create the Port Object */
920 Status
= NtCreatePort(&CsrSbApiPort
,
922 sizeof(SB_CONNECTION_INFO
),
924 32 * sizeof(SB_API_MSG
));
925 if (PortSd
) RtlFreeHeap(CsrHeap
, 0, PortSd
);
927 if (NT_SUCCESS(Status
))
929 /* Create the Thread to handle the API Requests */
930 Status
= RtlCreateUserThread(NtCurrentProcess(),
936 (PVOID
)CsrSbApiRequestThread
,
940 if (NT_SUCCESS(Status
))
942 /* Add it as a Static Server Thread */
943 CsrSbApiRequestThreadPtr
= CsrAddStaticServerThread(hRequestThread
,
948 Status
= NtResumeThread(hRequestThread
, NULL
);
956 /* PUBLIC FUNCTIONS ***********************************************************/
959 * @name CsrServerInitialization
962 * The CsrServerInitialization routine is the native (not Server) entrypoint
963 * of this Server DLL. It serves as the entrypoint for csrss.
965 * @param ArgumentCount
966 * Number of arguments on the command line.
969 * Array of arguments from the command line.
971 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
979 CsrServerInitialization(IN ULONG ArgumentCount
,
980 IN PCHAR Arguments
[])
982 NTSTATUS Status
= STATUS_SUCCESS
;
983 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
985 /* Create the Init Event */
986 Status
= NtCreateEvent(&CsrInitializationEvent
,
989 SynchronizationEvent
,
991 if (!NT_SUCCESS(Status
))
993 DPRINT1("CSRSRV:%s: NtCreateEvent failed (Status=%08lx)\n",
994 __FUNCTION__
, Status
);
998 /* Cache System Basic Information so we don't always request it */
999 Status
= NtQuerySystemInformation(SystemBasicInformation
,
1001 sizeof(SYSTEM_BASIC_INFORMATION
),
1003 if (!NT_SUCCESS(Status
))
1005 DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=%08lx)\n",
1006 __FUNCTION__
, Status
);
1011 CsrHeap
= RtlGetProcessHeap();
1013 /* Set our Security Descriptor to protect the process */
1014 Status
= CsrSetProcessSecurity();
1015 if (!NT_SUCCESS(Status
))
1017 DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=%08lx)\n",
1018 __FUNCTION__
, Status
);
1022 /* Set up Session Support */
1023 Status
= CsrInitializeNtSessionList();
1024 if (!NT_SUCCESS(Status
))
1026 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
1027 __FUNCTION__
, Status
);
1031 /* Set up Process Support and allocate the CSR Root Process */
1032 Status
= CsrInitializeProcessStructure();
1033 if (!NT_SUCCESS(Status
))
1035 DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=%08lx)\n",
1036 __FUNCTION__
, Status
);
1040 /* Parse the command line */
1041 Status
= CsrParseServerCommandLine(ArgumentCount
, Arguments
);
1042 if (!NT_SUCCESS(Status
))
1044 DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=%08lx)\n",
1045 __FUNCTION__
, Status
);
1049 /* Finish to initialize the CSR Root Process */
1050 Status
= CsrInitCsrRootProcess();
1051 if (!NT_SUCCESS(Status
))
1053 DPRINT1("CSRSRV:%s: CsrInitCsrRootProcess failed (Status=%08lx)\n",
1054 __FUNCTION__
, Status
);
1058 /* Now initialize our API Port */
1059 Status
= CsrApiPortInitialize();
1060 if (!NT_SUCCESS(Status
))
1062 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n",
1063 __FUNCTION__
, Status
);
1067 /* Initialize the API Port for SM communication */
1068 Status
= CsrSbApiPortInitialize();
1069 if (!NT_SUCCESS(Status
))
1071 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n",
1072 __FUNCTION__
, Status
);
1076 /* We're all set! Connect to SM! */
1077 Status
= SmConnectToSm(&CsrSbApiPortName
,
1079 IMAGE_SUBSYSTEM_WINDOWS_GUI
,
1081 if (!NT_SUCCESS(Status
))
1083 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n",
1084 __FUNCTION__
, Status
);
1088 /* Finito! Signal the event */
1089 Status
= NtSetEvent(CsrInitializationEvent
, NULL
);
1090 if (!NT_SUCCESS(Status
))
1092 DPRINT1("CSRSRV:%s: NtSetEvent failed (Status=%08lx)\n",
1093 __FUNCTION__
, Status
);
1097 /* Close the event handle now */
1098 NtClose(CsrInitializationEvent
);
1100 /* Have us handle Hard Errors */
1101 Status
= NtSetDefaultHardErrorPort(CsrApiPort
);
1102 if (!NT_SUCCESS(Status
))
1104 DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n",
1105 __FUNCTION__
, Status
);
1114 * @name CsrPopulateDosDevices
1115 * @unimplemented NT5.1
1117 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1118 * to populate the Dos Devices Object Directory for the session.
1129 CsrPopulateDosDevices(VOID
)
1131 DPRINT1("Deprecated API in r55585.\n");
1137 DllMain(IN HINSTANCE hInstanceDll
,
1139 IN LPVOID lpReserved
)
1141 /* We don't do much */
1142 UNREFERENCED_PARAMETER(hInstanceDll
);
1143 UNREFERENCED_PARAMETER(dwReason
);
1144 UNREFERENCED_PARAMETER(lpReserved
);