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
);
64 CallProcessCreated(IN PCSR_PROCESS SourceProcessData
,
65 IN PCSR_PROCESS TargetProcessData
)
67 NTSTATUS Status
= STATUS_SUCCESS
;
69 PCSR_SERVER_DLL ServerDll
;
71 DPRINT("CSR: %s called\n", __FUNCTION__
);
73 /* Notify the Server DLLs */
74 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
76 /* Get the current Server DLL */
77 ServerDll
= CsrLoadedServerDll
[i
];
79 /* Make sure it's valid and that it has callback */
80 if ((ServerDll
) && (ServerDll
->NewProcessCallback
))
82 Status
= ServerDll
->NewProcessCallback(SourceProcessData
, TargetProcessData
);
90 *** Some APIs from here will go to basesrv.dll, some others to winsrv.dll.
91 *** Furthermore, this structure uses the old definition of APIs list.
92 *** The new one is in fact three arrays, one of APIs pointers, one other of
93 *** corresponding indexes, and the third one of names (not very efficient...).
95 CSRSS_API_DEFINITION NativeDefinitions
[] =
97 CSRSS_DEFINE_API(CREATE_PROCESS
, CsrSrvCreateProcess
),
98 CSRSS_DEFINE_API(CREATE_THREAD
, CsrSrvCreateThread
),
99 CSRSS_DEFINE_API(TERMINATE_PROCESS
, CsrTerminateProcess
),
100 CSRSS_DEFINE_API(CONNECT_PROCESS
, CsrConnectProcess
),
101 CSRSS_DEFINE_API(REGISTER_SERVICES_PROCESS
, CsrRegisterServicesProcess
),
102 CSRSS_DEFINE_API(GET_SHUTDOWN_PARAMETERS
, CsrGetShutdownParameters
),
103 CSRSS_DEFINE_API(SET_SHUTDOWN_PARAMETERS
, CsrSetShutdownParameters
),
107 /* === INIT ROUTINES === */
110 * @name CsrSetProcessSecurity
112 * The CsrSetProcessSecurity routine protects access to the CSRSS process
113 * from unauthorized tampering.
117 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
125 CsrSetProcessSecurity(VOID
)
128 HANDLE hToken
, hProcess
= NtCurrentProcess();
130 PTOKEN_USER TokenInfo
= NULL
;
131 PSECURITY_DESCRIPTOR ProcSd
= NULL
;
136 Status
= NtOpenProcessToken(hProcess
, TOKEN_QUERY
, &hToken
);
137 if (!NT_SUCCESS(Status
)) goto Quickie
;
139 /* Get the Token User Length */
140 NtQueryInformationToken(hToken
, TokenUser
, NULL
, 0, &Length
);
142 /* Allocate space for it */
143 TokenInfo
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Length
);
146 Status
= STATUS_NO_MEMORY
;
150 /* Now query the data */
151 Status
= NtQueryInformationToken(hToken
, TokenUser
, TokenInfo
, Length
, &Length
);
153 if (!NT_SUCCESS(Status
)) goto Quickie
;
155 /* Now check the SID Length */
156 UserSid
= TokenInfo
->User
.Sid
;
157 Length
= RtlLengthSid(UserSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
159 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
160 ProcSd
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
163 Status
= STATUS_NO_MEMORY
;
167 /* Set the pointer to the DACL */
168 Dacl
= (PACL
)((ULONG_PTR
)ProcSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
170 /* Now create the SD itself */
171 Status
= RtlCreateSecurityDescriptor(ProcSd
, SECURITY_DESCRIPTOR_REVISION
);
172 if (!NT_SUCCESS(Status
))
174 DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status
);
178 /* Create the DACL for it*/
179 Status
= RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
180 if (!NT_SUCCESS(Status
))
182 DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status
);
187 Status
= RtlAddAccessAllowedAce(Dacl
,
189 PROCESS_VM_READ
| PROCESS_VM_WRITE
|
190 PROCESS_VM_OPERATION
| PROCESS_DUP_HANDLE
|
191 PROCESS_TERMINATE
| PROCESS_SUSPEND_RESUME
|
192 PROCESS_QUERY_INFORMATION
| READ_CONTROL
,
194 if (!NT_SUCCESS(Status
))
196 DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status
);
200 /* Clear the DACL in the SD */
201 Status
= RtlSetDaclSecurityDescriptor(ProcSd
, TRUE
, Dacl
, FALSE
);
202 if (!NT_SUCCESS(Status
))
204 DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status
);
208 /* Write the SD into the Process */
209 Status
= NtSetSecurityObject(hProcess
, DACL_SECURITY_INFORMATION
, ProcSd
);
210 if (!NT_SUCCESS(Status
))
212 DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status
);
216 /* Free the memory and return */
218 if (ProcSd
) RtlFreeHeap(CsrHeap
, 0, ProcSd
);
219 RtlFreeHeap(CsrHeap
, 0, TokenInfo
);
224 * @name CsrSetDirectorySecurity
226 * The CsrSetDirectorySecurity routine sets the security descriptor for the
227 * specified Object Directory.
229 * @param ObjectDirectory
230 * Handle fo the Object Directory to protect.
232 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
240 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory
)
242 /* FIXME: Implement */
243 return STATUS_SUCCESS
;
247 * @name GetDosDevicesProtection
249 * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
252 * @param DosDevicesSd
253 * Pointer to the Security Descriptor to return.
255 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
258 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
259 * regular users may or may not have full access to the directory.
264 GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd
)
266 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
267 SID_IDENTIFIER_AUTHORITY CreatorAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
268 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
269 PSID WorldSid
, CreatorSid
, AdminSid
, SystemSid
;
270 UCHAR KeyValueBuffer
[0x40];
271 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
272 UNICODE_STRING KeyName
;
273 ULONG ProtectionMode
= 0;
274 OBJECT_ATTRIBUTES ObjectAttributes
;
276 PACCESS_ALLOWED_ACE Ace
;
279 ULONG ResultLength
, SidLength
, AclLength
;
282 Status
= RtlCreateSecurityDescriptor(DosDevicesSd
, SECURITY_DESCRIPTOR_REVISION
);
283 ASSERT(NT_SUCCESS(Status
));
285 /* Initialize the System SID */
286 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
287 SECURITY_LOCAL_SYSTEM_RID
,
290 ASSERT(NT_SUCCESS(Status
));
292 /* Initialize the World SID */
293 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
, 1,
297 ASSERT(NT_SUCCESS(Status
));
299 /* Initialize the Admin SID */
300 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
, 2,
301 SECURITY_BUILTIN_DOMAIN_RID
,
302 DOMAIN_ALIAS_RID_ADMINS
,
305 ASSERT(NT_SUCCESS(Status
));
307 /* Initialize the Creator SID */
308 Status
= RtlAllocateAndInitializeSid(&CreatorAuthority
, 1,
309 SECURITY_CREATOR_OWNER_RID
,
312 ASSERT(NT_SUCCESS(Status
));
314 /* Open the Session Manager Key */
315 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
316 InitializeObjectAttributes(&ObjectAttributes
,
318 OBJ_CASE_INSENSITIVE
,
321 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
322 if (NT_SUCCESS(Status
))
324 /* Read the key value */
325 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
326 Status
= NtQueryValueKey(hKey
,
328 KeyValuePartialInformation
,
330 sizeof(KeyValueBuffer
),
333 /* Make sure it's what we expect it to be */
334 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
335 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
336 (*(PULONG
)KeyValuePartialInfo
->Data
))
338 /* Save the Protection Mode */
339 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
342 /* Close the handle */
346 /* Check the Protection Mode */
347 if (ProtectionMode
& 3)
349 /* Calculate SID Lengths */
350 SidLength
= RtlLengthSid(CreatorSid
) + RtlLengthSid(SystemSid
) +
351 RtlLengthSid(AdminSid
);
352 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
354 /* Allocate memory for the DACL */
355 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
356 ASSERT(Dacl
!= NULL
);
358 /* Build the ACL and add 3 ACEs */
359 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
360 ASSERT(NT_SUCCESS(Status
));
361 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
362 ASSERT(NT_SUCCESS(Status
));
363 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, AdminSid
);
364 ASSERT(NT_SUCCESS(Status
));
365 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, CreatorSid
);
366 ASSERT(NT_SUCCESS(Status
));
368 /* Edit the ACEs to make them inheritable */
369 Status
= RtlGetAce(Dacl
, 0, (PVOID
*)&Ace
);
370 ASSERT(NT_SUCCESS(Status
));
371 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
372 Status
= RtlGetAce(Dacl
, 1, (PVOID
*)&Ace
);
373 ASSERT(NT_SUCCESS(Status
));
374 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
375 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
376 ASSERT(NT_SUCCESS(Status
));
377 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
379 /* Set this DACL with the SD */
380 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
381 ASSERT(NT_SUCCESS(Status
));
386 /* Calculate SID Lengths */
387 SidLength
= RtlLengthSid(WorldSid
) + RtlLengthSid(SystemSid
);
388 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) + SidLength
;
390 /* Allocate memory for the DACL */
391 Dacl
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, AclLength
);
392 ASSERT(Dacl
!= NULL
);
394 /* Build the ACL and add 3 ACEs */
395 Status
= RtlCreateAcl(Dacl
, AclLength
, ACL_REVISION2
);
396 ASSERT(NT_SUCCESS(Status
));
397 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
, WorldSid
);
398 ASSERT(NT_SUCCESS(Status
));
399 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, SystemSid
);
400 ASSERT(NT_SUCCESS(Status
));
401 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, GENERIC_ALL
, WorldSid
);
402 ASSERT(NT_SUCCESS(Status
));
404 /* Edit the last ACE to make it inheritable */
405 Status
= RtlGetAce(Dacl
, 2, (PVOID
*)&Ace
);
406 ASSERT(NT_SUCCESS(Status
));
407 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
| INHERIT_ONLY_ACE
;
409 /* Set this DACL with the SD */
410 Status
= RtlSetDaclSecurityDescriptor(DosDevicesSd
, TRUE
, Dacl
, FALSE
);
411 ASSERT(NT_SUCCESS(Status
));
415 /* FIXME: failure cases! Fail: */
416 /* Free the memory */
417 RtlFreeHeap(CsrHeap
, 0, Dacl
);
419 /* FIXME: semi-failure cases! Quickie: */
422 RtlFreeSid(SystemSid
);
423 RtlFreeSid(WorldSid
);
424 RtlFreeSid(AdminSid
);
425 RtlFreeSid(CreatorSid
);
432 * @name FreeDosDevicesProtection
434 * The FreeDosDevicesProtection frees the security descriptor that was created
435 * by GetDosDevicesProtection
437 * @param DosDevicesSd
438 * Pointer to the security descriptor to free.
447 FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd
)
450 BOOLEAN Present
, Default
;
453 /* Get the DACL corresponding to this SD */
454 Status
= RtlGetDaclSecurityDescriptor(DosDevicesSd
, &Present
, &Dacl
, &Default
);
455 ASSERT(NT_SUCCESS(Status
));
457 ASSERT(Dacl
!= NULL
);
460 if ((NT_SUCCESS(Status
)) && (Dacl
)) RtlFreeHeap(CsrHeap
, 0, Dacl
);
464 * @name CsrCreateSessionObjectDirectory
466 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
467 * Session and Dos Devices directories for the specified session.
470 * Session ID for which to create the directories.
472 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
480 CsrCreateSessionObjectDirectory(IN ULONG Session
)
482 WCHAR SessionBuffer
[512], BnoBuffer
[512];
483 UNICODE_STRING SessionString
, BnoString
;
484 OBJECT_ATTRIBUTES ObjectAttributes
;
486 SECURITY_DESCRIPTOR DosDevicesSd
;
489 /* Generate the Session BNOLINKS Directory name */
490 swprintf(SessionBuffer
, L
"%ws\\BNOLINKS", SESSION_ROOT
);
491 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
494 InitializeObjectAttributes(&ObjectAttributes
,
496 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
499 Status
= NtCreateDirectoryObject(&BNOLinksDirectory
,
500 DIRECTORY_ALL_ACCESS
,
502 if (!NT_SUCCESS(Status
))
504 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
505 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
509 /* Now add the Session ID */
510 swprintf(SessionBuffer
, L
"%ld", Session
);
511 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
513 /* Check if this is the first Session */
516 /* Not the first, so the name will be slighly more complex */
517 swprintf(BnoBuffer
, L
"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT
, Session
);
518 RtlInitUnicodeString(&BnoString
, BnoBuffer
);
522 /* Use the direct name */
523 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
526 /* Create the symlink */
527 InitializeObjectAttributes(&ObjectAttributes
,
529 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
532 Status
= NtCreateSymbolicLinkObject(&BnoHandle
,
533 SYMBOLIC_LINK_ALL_ACCESS
,
536 if (!NT_SUCCESS(Status
))
538 DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
539 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
543 /* Create the \DosDevices Security Descriptor */
544 Status
= GetDosDevicesProtection(&DosDevicesSd
);
545 if (!NT_SUCCESS(Status
)) return Status
;
547 /* Now create a directory for this session */
548 swprintf(SessionBuffer
, L
"%ws\\%ld", SESSION_ROOT
, Session
);
549 RtlInitUnicodeString(&SessionString
, SessionBuffer
);
551 /* Create the directory */
552 InitializeObjectAttributes(&ObjectAttributes
,
554 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
557 Status
= NtCreateDirectoryObject(&SessionObjectDirectory
,
558 DIRECTORY_ALL_ACCESS
,
560 if (!NT_SUCCESS(Status
))
562 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
563 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
564 FreeDosDevicesProtection(&DosDevicesSd
);
568 /* Next, create a directory for this session's DOS Devices */
569 RtlInitUnicodeString(&SessionString
, L
"DosDevices");
570 InitializeObjectAttributes(&ObjectAttributes
,
572 OBJ_CASE_INSENSITIVE
,
573 SessionObjectDirectory
,
575 Status
= NtCreateDirectoryObject(&DosDevicesDirectory
,
576 DIRECTORY_ALL_ACCESS
,
578 if (!NT_SUCCESS(Status
))
580 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
581 "CsrCreateSessionObjectDirectory - status = %lx\n", Status
);
584 /* Release the Security Descriptor */
585 FreeDosDevicesProtection(&DosDevicesSd
);
592 * @name CsrParseServerCommandLine
594 * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
595 * registry and performs operations for each entry found.
597 * @param ArgumentCount
598 * Number of arguments on the command line.
601 * Array of arguments.
603 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
611 CsrParseServerCommandLine(IN ULONG ArgumentCount
,
612 IN PCHAR Arguments
[])
615 PCHAR ParameterName
= NULL
, ParameterValue
= NULL
, EntryPoint
, ServerString
;
617 ANSI_STRING AnsiString
;
618 OBJECT_ATTRIBUTES ObjectAttributes
;
620 /* Set the Defaults */
621 CsrTotalPerProcessDataLength
= 0;
622 CsrObjectDirectory
= NULL
;
623 CsrMaxApiRequestThreads
= 16;
625 /* Save our Session ID, and create a Directory for it */
626 SessionId
= NtCurrentPeb()->SessionId
;
627 Status
= CsrCreateSessionObjectDirectory(SessionId
);
628 if (!NT_SUCCESS(Status
))
630 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
633 /* It's not fatal if the session ID isn't zero */
634 if (SessionId
) return Status
;
635 ASSERT(NT_SUCCESS(Status
));
638 /* Loop through every argument */
639 for (i
= 1; i
< ArgumentCount
; i
++)
641 /* Split Name and Value */
642 ParameterName
= Arguments
[i
];
643 ParameterValue
= NULL
;
644 ParameterValue
= strchr(ParameterName
, '=');
645 if (ParameterValue
) *ParameterValue
++ = ANSI_NULL
;
646 DPRINT1("Name=%s, Value=%s\n", ParameterName
, ParameterValue
);
648 /* Check for Object Directory */
649 if (_stricmp(ParameterName
, "ObjectDirectory") == 0)
651 /* Check if a session ID is specified */
654 DPRINT1("Sessions not yet implemented\n");
658 /* Initialize the directory name */
659 RtlInitAnsiString(&AnsiString
, ParameterValue
);
660 Status
= RtlAnsiStringToUnicodeString(&CsrDirectoryName
,
663 ASSERT(NT_SUCCESS(Status
) || SessionId
!= 0);
664 if (!NT_SUCCESS(Status
)) return Status
;
667 InitializeObjectAttributes(&ObjectAttributes
,
669 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
| OBJ_PERMANENT
,
672 Status
= NtCreateDirectoryObject(&CsrObjectDirectory
,
673 DIRECTORY_ALL_ACCESS
,
675 if (!NT_SUCCESS(Status
)) return Status
;
678 Status
= CsrSetDirectorySecurity(CsrObjectDirectory
);
679 if (!NT_SUCCESS(Status
)) return Status
;
681 else if (_stricmp(ParameterName
, "SubSystemType") == 0)
685 else if (_stricmp(ParameterName
, "MaxRequestThreads") == 0)
687 Status
= RtlCharToInteger(ParameterValue
,
689 &CsrMaxApiRequestThreads
);
691 else if (_stricmp(ParameterName
, "RequestThreads") == 0)
694 Status
= STATUS_SUCCESS
;
696 else if (_stricmp(ParameterName
, "ProfileControl") == 0)
700 else if (_stricmp(ParameterName
, "SharedSection") == 0)
702 /* Create the Section */
703 Status
= CsrSrvCreateSharedSection(ParameterValue
);
704 if (!NT_SUCCESS(Status
))
706 DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
707 ParameterName
, ParameterValue
, Status
);
712 Status
= CsrLoadServerDll("CSRSS" /* "CSRSRV" */, NULL
, CSR_SRV_SERVER
);
714 else if (_stricmp(ParameterName
, "ServerDLL") == 0)
716 /* Loop the command line */
718 Status
= STATUS_INVALID_PARAMETER
;
719 ServerString
= ParameterValue
;
720 while (*ServerString
)
722 /* Check for the Entry Point */
723 if ((*ServerString
== ':') && (!EntryPoint
))
725 /* Found it. Add a nullchar and save it */
726 *ServerString
++ = ANSI_NULL
;
727 EntryPoint
= ServerString
;
730 /* Check for the Dll Index */
731 if (*ServerString
++ == ',') break;
734 /* Did we find something to load? */
737 DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
738 ParameterValue
, Status
);
742 /* Convert it to a ULONG */
743 Status
= RtlCharToInteger(ServerString
, 10, &DllIndex
);
745 /* Add a null char if it was valid */
746 if (NT_SUCCESS(Status
)) ServerString
[-1] = ANSI_NULL
;
749 if (CsrDebug
& 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue
, EntryPoint
);
750 Status
= CsrLoadServerDll(ParameterValue
, EntryPoint
, DllIndex
);
751 if (!NT_SUCCESS(Status
))
753 DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
754 ParameterValue
, Status
);
758 else if (_stricmp(ParameterName
, "Windows") == 0)
761 // Check whether we want to start in pure GUI or pure CLI.
765 /* Invalid parameter on the command line */
766 Status
= STATUS_INVALID_PARAMETER
;
775 * @name CsrCreateLocalSystemSD
777 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
778 * the local account with PORT_ALL_ACCESS.
780 * @param LocalSystemSd
781 * Pointer to a pointer to the security descriptor to create.
783 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
791 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR
*LocalSystemSd
)
793 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
796 PSECURITY_DESCRIPTOR SystemSd
;
800 /* Initialize the System SID */
801 RtlAllocateAndInitializeSid(&NtSidAuthority
, 1,
802 SECURITY_LOCAL_SYSTEM_RID
,
806 /* Get the length of the SID */
807 Length
= RtlLengthSid(SystemSid
) + sizeof(ACL
) + sizeof(ACCESS_ALLOWED_ACE
);
809 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
810 SystemSd
= RtlAllocateHeap(CsrHeap
, 0, SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
812 /* Set the pointer to the DACL */
813 Dacl
= (PACL
)((ULONG_PTR
)SystemSd
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
815 /* Now create the SD itself */
816 Status
= RtlCreateSecurityDescriptor(SystemSd
, SECURITY_DESCRIPTOR_REVISION
);
817 if (!NT_SUCCESS(Status
))
820 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
824 /* Create the DACL for it */
825 RtlCreateAcl(Dacl
, Length
, ACL_REVISION2
);
828 Status
= RtlAddAccessAllowedAce(Dacl
, ACL_REVISION
, PORT_ALL_ACCESS
, SystemSid
);
829 if (!NT_SUCCESS(Status
))
832 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
836 /* Clear the DACL in the SD */
837 Status
= RtlSetDaclSecurityDescriptor(SystemSd
, TRUE
, Dacl
, FALSE
);
838 if (!NT_SUCCESS(Status
))
841 RtlFreeHeap(CsrHeap
, 0, SystemSd
);
845 /* Free the SID and return*/
846 RtlFreeSid(SystemSid
);
847 *LocalSystemSd
= SystemSd
;
852 * @name CsrSbApiPortInitialize
854 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
855 * communications with the Session Manager (SM) and initializes the static
856 * thread that will handle connection requests and APIs.
860 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
868 CsrSbApiPortInitialize(VOID
)
871 PSECURITY_DESCRIPTOR PortSd
;
872 OBJECT_ATTRIBUTES ObjectAttributes
;
874 HANDLE hRequestThread
;
877 /* Calculate how much space we'll need for the Port Name */
878 Size
= CsrDirectoryName
.Length
+ sizeof(SB_PORT_NAME
) + sizeof(WCHAR
);
880 /* Create the buffer for it */
881 CsrSbApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
882 if (!CsrSbApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
884 /* Setup the rest of the empty string */
885 CsrSbApiPortName
.Length
= 0;
886 CsrSbApiPortName
.MaximumLength
= (USHORT
)Size
;
888 /* Now append the full port name */
889 RtlAppendUnicodeStringToString(&CsrSbApiPortName
, &CsrDirectoryName
);
890 RtlAppendUnicodeToString(&CsrSbApiPortName
, UNICODE_PATH_SEP
);
891 RtlAppendUnicodeToString(&CsrSbApiPortName
, SB_PORT_NAME
);
892 if (CsrDebug
& 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName
);
894 /* Create Security Descriptor for this Port */
895 Status
= CsrCreateLocalSystemSD(&PortSd
);
896 if (!NT_SUCCESS(Status
)) return Status
;
898 /* Initialize the Attributes */
899 InitializeObjectAttributes(&ObjectAttributes
,
905 /* Create the Port Object */
906 Status
= NtCreatePort(&CsrSbApiPort
,
908 sizeof(SB_CONNECTION_INFO
),
910 32 * sizeof(SB_API_MSG
));
911 if (PortSd
) RtlFreeHeap(CsrHeap
, 0, PortSd
);
913 if (NT_SUCCESS(Status
))
915 /* Create the Thread to handle the API Requests */
916 Status
= RtlCreateUserThread(NtCurrentProcess(),
922 (PVOID
)CsrSbApiRequestThread
,
926 if (NT_SUCCESS(Status
))
928 /* Add it as a Static Server Thread */
929 CsrSbApiRequestThreadPtr
= CsrAddStaticServerThread(hRequestThread
,
934 Status
= NtResumeThread(hRequestThread
, NULL
);
943 /* PUBLIC FUNCTIONS ***********************************************************/
946 * @name CsrServerInitialization
949 * The CsrServerInitialization routine is the native (not Server) entrypoint
950 * of this Server DLL. It serves as the entrypoint for csrss.
952 * @param ArgumentCount
953 * Number of arguments on the command line.
956 * Array of arguments from the command line.
958 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
966 CsrServerInitialization(IN ULONG ArgumentCount
,
967 IN PCHAR Arguments
[])
969 NTSTATUS Status
= STATUS_SUCCESS
;
970 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
972 /* Create the Init Event */
973 Status
= NtCreateEvent(&CsrInitializationEvent
,
976 SynchronizationEvent
,
978 if (!NT_SUCCESS(Status
))
980 DPRINT1("CSRSRV:%s: NtCreateEvent failed (Status=%08lx)\n",
981 __FUNCTION__
, Status
);
985 /* Cache System Basic Information so we don't always request it */
986 Status
= NtQuerySystemInformation(SystemBasicInformation
,
988 sizeof(SYSTEM_BASIC_INFORMATION
),
990 if (!NT_SUCCESS(Status
))
992 DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=%08lx)\n",
993 __FUNCTION__
, Status
);
998 CsrHeap
= RtlGetProcessHeap();
1000 /* Set our Security Descriptor to protect the process */
1001 Status
= CsrSetProcessSecurity();
1002 if (!NT_SUCCESS(Status
))
1004 DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=%08lx)\n",
1005 __FUNCTION__
, Status
);
1009 /* Set up Session Support */
1010 Status
= CsrInitializeNtSessionList();
1011 if (!NT_SUCCESS(Status
))
1013 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
1014 __FUNCTION__
, Status
);
1018 /* Set up Process Support */
1019 Status
= CsrInitializeProcessStructure();
1020 if (!NT_SUCCESS(Status
))
1022 DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=%08lx)\n",
1023 __FUNCTION__
, Status
);
1027 /* Parse the command line */
1028 Status
= CsrParseServerCommandLine(ArgumentCount
, Arguments
);
1029 if (!NT_SUCCESS(Status
))
1031 DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=%08lx)\n",
1032 __FUNCTION__
, Status
);
1036 Status
= CsrApiRegisterDefinitions(NativeDefinitions
);
1037 if (!NT_SUCCESS(Status
))
1039 DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrApiRegisterDefinitions", Status
);
1042 /* Now initialize our API Port */
1043 Status
= CsrApiPortInitialize();
1044 if (!NT_SUCCESS(Status
))
1046 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n",
1047 __FUNCTION__
, Status
);
1051 //////////////////////////// ADDED ////////////////////////////
1053 /\* Initialize Win32csr *\/
1054 Status = CsrLoadServerDll("win32csr", "Win32CsrInitialization", 2);
1055 if (!NT_SUCCESS(Status))
1057 DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrLoadServerDll", Status);
1060 //////////////////////////// END ADDED ////////////////////////////
1062 /* Initialize the API Port for SM communication */
1063 Status
= CsrSbApiPortInitialize();
1064 if (!NT_SUCCESS(Status
))
1066 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n",
1067 __FUNCTION__
, Status
);
1071 /* We're all set! Connect to SM! */
1072 Status
= SmConnectToSm(&CsrSbApiPortName
,
1074 IMAGE_SUBSYSTEM_WINDOWS_GUI
,
1076 if (!NT_SUCCESS(Status
))
1078 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n",
1079 __FUNCTION__
, Status
);
1083 /* Finito! Signal the event */
1084 Status
= NtSetEvent(CsrInitializationEvent
, NULL
);
1085 if (!NT_SUCCESS(Status
))
1087 DPRINT1("CSRSRV:%s: NtSetEvent failed (Status=%08lx)\n",
1088 __FUNCTION__
, Status
);
1092 /* Close the event handle now */
1093 NtClose(CsrInitializationEvent
);
1095 /* Have us handle Hard Errors */
1096 Status
= NtSetDefaultHardErrorPort(CsrApiPort
);
1097 if (!NT_SUCCESS(Status
))
1099 DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n",
1100 __FUNCTION__
, Status
);
1109 * @name CsrPopulateDosDevices
1110 * @unimplemented NT5.1
1112 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1113 * to populate the Dos Devices Object Directory for the session.
1124 CsrPopulateDosDevices(VOID
)
1126 DPRINT1("Deprecated API\n");
1132 DllMain(IN HANDLE hDll
,
1134 IN LPVOID lpReserved
)
1136 /* We don't do much */
1137 UNREFERENCED_PARAMETER(hDll
);
1138 UNREFERENCED_PARAMETER(dwReason
);
1139 UNREFERENCED_PARAMETER(lpReserved
);