4b08d5feeb4e2cb6b6a018913243116372c34753
[reactos.git] / reactos / subsystems / win32 / csrsrv / init.c
1 /*
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
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include "srv.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* DATA ***********************************************************************/
18
19 HANDLE CsrHeap = NULL;
20 HANDLE CsrObjectDirectory = NULL;
21 UNICODE_STRING CsrDirectoryName;
22 UNICODE_STRING CsrSbApiPortName;
23 HANDLE CsrSbApiPort = NULL;
24 PCSR_THREAD CsrSbApiRequestThreadPtr;
25 HANDLE CsrSmApiPort = NULL;
26 HANDLE hSbApiPort = NULL;
27 HANDLE CsrApiPort = NULL;
28 ULONG CsrDebug = 0; // 0xFFFFFFFF;
29 ULONG CsrMaxApiRequestThreads;
30 ULONG CsrTotalPerProcessDataLength;
31 ULONG SessionId;
32 HANDLE BNOLinksDirectory;
33 HANDLE SessionObjectDirectory;
34 HANDLE DosDevicesDirectory;
35 SYSTEM_BASIC_INFORMATION CsrNtSysInfo;
36
37
38 /* PRIVATE FUNCTIONS **********************************************************/
39
40 /* === INIT ROUTINES === */
41
42 /*++
43 * @name CsrSetProcessSecurity
44 *
45 * The CsrSetProcessSecurity routine protects access to the CSRSS process
46 * from unauthorized tampering.
47 *
48 * @param None.
49 *
50 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
51 *
52 * @remarks None.
53 *
54 *--*/
55 NTSTATUS
56 NTAPI
57 CsrSetProcessSecurity(VOID)
58 {
59 NTSTATUS Status;
60 HANDLE hToken, hProcess = NtCurrentProcess();
61 ULONG Length;
62 PTOKEN_USER TokenInfo = NULL;
63 PSECURITY_DESCRIPTOR ProcSd = NULL;
64 PACL Dacl;
65 PSID UserSid;
66
67 /* Open our token */
68 Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
69 if (!NT_SUCCESS(Status)) goto Quickie;
70
71 /* Get the Token User Length */
72 NtQueryInformationToken(hToken, TokenUser, NULL, 0, &Length);
73
74 /* Allocate space for it */
75 TokenInfo = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length);
76 if (!TokenInfo)
77 {
78 Status = STATUS_NO_MEMORY;
79 goto Quickie;
80 }
81
82 /* Now query the data */
83 Status = NtQueryInformationToken(hToken, TokenUser, TokenInfo, Length, &Length);
84 NtClose(hToken);
85 if (!NT_SUCCESS(Status)) goto Quickie;
86
87 /* Now check the SID Length */
88 UserSid = TokenInfo->User.Sid;
89 Length = RtlLengthSid(UserSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE);
90
91 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
92 ProcSd = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
93 if (!ProcSd)
94 {
95 Status = STATUS_NO_MEMORY;
96 goto Quickie;
97 }
98
99 /* Set the pointer to the DACL */
100 Dacl = (PACL)((ULONG_PTR)ProcSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
101
102 /* Now create the SD itself */
103 Status = RtlCreateSecurityDescriptor(ProcSd, SECURITY_DESCRIPTOR_REVISION);
104 if (!NT_SUCCESS(Status))
105 {
106 DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status);
107 goto Quickie;
108 }
109
110 /* Create the DACL for it*/
111 Status = RtlCreateAcl(Dacl, Length, ACL_REVISION2);
112 if (!NT_SUCCESS(Status))
113 {
114 DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status);
115 goto Quickie;
116 }
117
118 /* Create the ACE */
119 Status = RtlAddAccessAllowedAce(Dacl,
120 ACL_REVISION,
121 PROCESS_VM_READ | PROCESS_VM_WRITE |
122 PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE |
123 PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME |
124 PROCESS_QUERY_INFORMATION | READ_CONTROL,
125 UserSid);
126 if (!NT_SUCCESS(Status))
127 {
128 DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status);
129 goto Quickie;
130 }
131
132 /* Clear the DACL in the SD */
133 Status = RtlSetDaclSecurityDescriptor(ProcSd, TRUE, Dacl, FALSE);
134 if (!NT_SUCCESS(Status))
135 {
136 DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status);
137 goto Quickie;
138 }
139
140 /* Write the SD into the Process */
141 Status = NtSetSecurityObject(hProcess, DACL_SECURITY_INFORMATION, ProcSd);
142 if (!NT_SUCCESS(Status))
143 {
144 DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status);
145 goto Quickie;
146 }
147
148 /* Free the memory and return */
149 Quickie:
150 if (ProcSd) RtlFreeHeap(CsrHeap, 0, ProcSd);
151 RtlFreeHeap(CsrHeap, 0, TokenInfo);
152 return Status;
153 }
154
155 /*++
156 * @name CsrSetDirectorySecurity
157 *
158 * The CsrSetDirectorySecurity routine sets the security descriptor for the
159 * specified Object Directory.
160 *
161 * @param ObjectDirectory
162 * Handle fo the Object Directory to protect.
163 *
164 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
165 *
166 * @remarks None.
167 *
168 *--*/
169 NTSTATUS
170 NTAPI
171 CsrSetDirectorySecurity(IN HANDLE ObjectDirectory)
172 {
173 /* FIXME: Implement */
174 return STATUS_SUCCESS;
175 }
176
177 /*++
178 * @name GetDosDevicesProtection
179 *
180 * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
181 * Object Directory.
182 *
183 * @param DosDevicesSd
184 * Pointer to the Security Descriptor to return.
185 *
186 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
187 *
188 * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
189 * regular users may or may not have full access to the directory.
190 *
191 *--*/
192 NTSTATUS
193 NTAPI
194 GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd)
195 {
196 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
197 SID_IDENTIFIER_AUTHORITY CreatorAuthority = {SECURITY_CREATOR_SID_AUTHORITY};
198 SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
199 PSID WorldSid, CreatorSid, AdminSid, SystemSid;
200 UCHAR KeyValueBuffer[0x40];
201 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
202 UNICODE_STRING KeyName;
203 ULONG ProtectionMode = 0;
204 OBJECT_ATTRIBUTES ObjectAttributes;
205 PACL Dacl;
206 PACCESS_ALLOWED_ACE Ace;
207 HANDLE hKey;
208 NTSTATUS Status;
209 ULONG ResultLength, SidLength, AclLength;
210
211 /* Create the SD */
212 Status = RtlCreateSecurityDescriptor(DosDevicesSd, SECURITY_DESCRIPTOR_REVISION);
213 ASSERT(NT_SUCCESS(Status));
214
215 /* Initialize the System SID */
216 Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 1,
217 SECURITY_LOCAL_SYSTEM_RID,
218 0, 0, 0, 0, 0, 0, 0,
219 &SystemSid);
220 ASSERT(NT_SUCCESS(Status));
221
222 /* Initialize the World SID */
223 Status = RtlAllocateAndInitializeSid(&WorldAuthority, 1,
224 SECURITY_WORLD_RID,
225 0, 0, 0, 0, 0, 0, 0,
226 &WorldSid);
227 ASSERT(NT_SUCCESS(Status));
228
229 /* Initialize the Admin SID */
230 Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 2,
231 SECURITY_BUILTIN_DOMAIN_RID,
232 DOMAIN_ALIAS_RID_ADMINS,
233 0, 0, 0, 0, 0, 0,
234 &AdminSid);
235 ASSERT(NT_SUCCESS(Status));
236
237 /* Initialize the Creator SID */
238 Status = RtlAllocateAndInitializeSid(&CreatorAuthority, 1,
239 SECURITY_CREATOR_OWNER_RID,
240 0, 0, 0, 0, 0, 0, 0,
241 &CreatorSid);
242 ASSERT(NT_SUCCESS(Status));
243
244 /* Open the Session Manager Key */
245 RtlInitUnicodeString(&KeyName, SM_REG_KEY);
246 InitializeObjectAttributes(&ObjectAttributes,
247 &KeyName,
248 OBJ_CASE_INSENSITIVE,
249 NULL,
250 NULL);
251 Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
252 if (NT_SUCCESS(Status))
253 {
254 /* Read the key value */
255 RtlInitUnicodeString(&KeyName, L"ProtectionMode");
256 Status = NtQueryValueKey(hKey,
257 &KeyName,
258 KeyValuePartialInformation,
259 KeyValueBuffer,
260 sizeof(KeyValueBuffer),
261 &ResultLength);
262
263 /* Make sure it's what we expect it to be */
264 KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
265 if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
266 (*(PULONG)KeyValuePartialInfo->Data))
267 {
268 /* Save the Protection Mode */
269 ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
270 }
271
272 /* Close the handle */
273 NtClose(hKey);
274 }
275
276 /* Check the Protection Mode */
277 if (ProtectionMode & 3)
278 {
279 /* Calculate SID Lengths */
280 SidLength = RtlLengthSid(CreatorSid) + RtlLengthSid(SystemSid) +
281 RtlLengthSid(AdminSid);
282 AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength;
283
284 /* Allocate memory for the DACL */
285 Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength);
286 ASSERT(Dacl != NULL);
287
288 /* Build the ACL and add 3 ACEs */
289 Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2);
290 ASSERT(NT_SUCCESS(Status));
291 Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid);
292 ASSERT(NT_SUCCESS(Status));
293 Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, AdminSid);
294 ASSERT(NT_SUCCESS(Status));
295 Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, CreatorSid);
296 ASSERT(NT_SUCCESS(Status));
297
298 /* Edit the ACEs to make them inheritable */
299 Status = RtlGetAce(Dacl, 0, (PVOID*)&Ace);
300 ASSERT(NT_SUCCESS(Status));
301 Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
302 Status = RtlGetAce(Dacl, 1, (PVOID*)&Ace);
303 ASSERT(NT_SUCCESS(Status));
304 Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
305 Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace);
306 ASSERT(NT_SUCCESS(Status));
307 Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
308
309 /* Set this DACL with the SD */
310 Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE);
311 ASSERT(NT_SUCCESS(Status));
312 goto Quickie;
313 }
314 else
315 {
316 /* Calculate SID Lengths */
317 SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(SystemSid);
318 AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength;
319
320 /* Allocate memory for the DACL */
321 Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength);
322 ASSERT(Dacl != NULL);
323
324 /* Build the ACL and add 3 ACEs */
325 Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2);
326 ASSERT(NT_SUCCESS(Status));
327 Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, WorldSid);
328 ASSERT(NT_SUCCESS(Status));
329 Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid);
330 ASSERT(NT_SUCCESS(Status));
331 Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, WorldSid);
332 ASSERT(NT_SUCCESS(Status));
333
334 /* Edit the last ACE to make it inheritable */
335 Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace);
336 ASSERT(NT_SUCCESS(Status));
337 Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
338
339 /* Set this DACL with the SD */
340 Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE);
341 ASSERT(NT_SUCCESS(Status));
342 goto Quickie;
343 }
344
345 /* FIXME: failure cases! Fail: */
346 /* Free the memory */
347 RtlFreeHeap(CsrHeap, 0, Dacl);
348
349 /* FIXME: semi-failure cases! Quickie: */
350 Quickie:
351 /* Free the SIDs */
352 RtlFreeSid(CreatorSid);
353 RtlFreeSid(AdminSid);
354 RtlFreeSid(WorldSid);
355 RtlFreeSid(SystemSid);
356
357 /* Return */
358 return Status;
359 }
360
361 /*++
362 * @name FreeDosDevicesProtection
363 *
364 * The FreeDosDevicesProtection frees the security descriptor that was created
365 * by GetDosDevicesProtection
366 *
367 * @param DosDevicesSd
368 * Pointer to the security descriptor to free.
369
370 * @return None.
371 *
372 * @remarks None.
373 *
374 *--*/
375 VOID
376 NTAPI
377 FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd)
378 {
379 PACL Dacl;
380 BOOLEAN Present, Default;
381 NTSTATUS Status;
382
383 /* Get the DACL corresponding to this SD */
384 Status = RtlGetDaclSecurityDescriptor(DosDevicesSd, &Present, &Dacl, &Default);
385 ASSERT(NT_SUCCESS(Status));
386 ASSERT(Present);
387 ASSERT(Dacl != NULL);
388
389 /* Free it */
390 if ((NT_SUCCESS(Status)) && (Dacl)) RtlFreeHeap(CsrHeap, 0, Dacl);
391 }
392
393 /*++
394 * @name CsrCreateSessionObjectDirectory
395 *
396 * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
397 * Session and Dos Devices directories for the specified session.
398 *
399 * @param Session
400 * Session ID for which to create the directories.
401 *
402 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
403 *
404 * @remarks None.
405 *
406 *--*/
407 NTSTATUS
408 NTAPI
409 CsrCreateSessionObjectDirectory(IN ULONG Session)
410 {
411 WCHAR SessionBuffer[512], BnoBuffer[512];
412 UNICODE_STRING SessionString, BnoString;
413 OBJECT_ATTRIBUTES ObjectAttributes;
414 HANDLE BnoHandle;
415 SECURITY_DESCRIPTOR DosDevicesSd;
416 NTSTATUS Status;
417
418 /* Generate the Session BNOLINKS Directory name */
419 swprintf(SessionBuffer, L"%ws\\BNOLINKS", SESSION_ROOT);
420 RtlInitUnicodeString(&SessionString, SessionBuffer);
421
422 /* Create it */
423 InitializeObjectAttributes(&ObjectAttributes,
424 &SessionString,
425 OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
426 NULL,
427 NULL);
428 Status = NtCreateDirectoryObject(&BNOLinksDirectory,
429 DIRECTORY_ALL_ACCESS,
430 &ObjectAttributes);
431 if (!NT_SUCCESS(Status))
432 {
433 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
434 "CsrCreateSessionObjectDirectory - status = %lx\n", Status);
435 return Status;
436 }
437
438 /* Now add the Session ID */
439 swprintf(SessionBuffer, L"%ld", Session);
440 RtlInitUnicodeString(&SessionString, SessionBuffer);
441
442 /* Check if this is the first Session */
443 if (Session)
444 {
445 /* Not the first, so the name will be slighly more complex */
446 swprintf(BnoBuffer, L"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT, Session);
447 RtlInitUnicodeString(&BnoString, BnoBuffer);
448 }
449 else
450 {
451 /* Use the direct name */
452 RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
453 }
454
455 /* Create the symlink */
456 InitializeObjectAttributes(&ObjectAttributes,
457 &SessionString,
458 OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
459 BNOLinksDirectory,
460 NULL);
461 Status = NtCreateSymbolicLinkObject(&BnoHandle,
462 SYMBOLIC_LINK_ALL_ACCESS,
463 &ObjectAttributes,
464 &BnoString);
465 if (!NT_SUCCESS(Status))
466 {
467 DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
468 "CsrCreateSessionObjectDirectory - status = %lx\n", Status);
469 return Status;
470 }
471
472 /* Create the \DosDevices Security Descriptor */
473 Status = GetDosDevicesProtection(&DosDevicesSd);
474 if (!NT_SUCCESS(Status)) return Status;
475
476 /* Now create a directory for this session */
477 swprintf(SessionBuffer, L"%ws\\%ld", SESSION_ROOT, Session);
478 RtlInitUnicodeString(&SessionString, SessionBuffer);
479
480 /* Create the directory */
481 InitializeObjectAttributes(&ObjectAttributes,
482 &SessionString,
483 OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
484 0,
485 &DosDevicesSd);
486 Status = NtCreateDirectoryObject(&SessionObjectDirectory,
487 DIRECTORY_ALL_ACCESS,
488 &ObjectAttributes);
489 if (!NT_SUCCESS(Status))
490 {
491 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
492 "CsrCreateSessionObjectDirectory - status = %lx\n", Status);
493 FreeDosDevicesProtection(&DosDevicesSd);
494 return Status;
495 }
496
497 /* Next, create a directory for this session's DOS Devices */
498 RtlInitUnicodeString(&SessionString, L"DosDevices");
499 InitializeObjectAttributes(&ObjectAttributes,
500 &SessionString,
501 OBJ_CASE_INSENSITIVE,
502 SessionObjectDirectory,
503 &DosDevicesSd);
504 Status = NtCreateDirectoryObject(&DosDevicesDirectory,
505 DIRECTORY_ALL_ACCESS,
506 &ObjectAttributes);
507 if (!NT_SUCCESS(Status))
508 {
509 DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
510 "CsrCreateSessionObjectDirectory - status = %lx\n", Status);
511 }
512
513 /* Release the Security Descriptor */
514 FreeDosDevicesProtection(&DosDevicesSd);
515
516 /* Return */
517 return Status;
518 }
519
520 /*++
521 * @name CsrParseServerCommandLine
522 *
523 * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
524 * registry and performs operations for each entry found.
525 *
526 * @param ArgumentCount
527 * Number of arguments on the command line.
528 *
529 * @param Arguments
530 * Array of arguments.
531 *
532 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
533 *
534 * @remarks None.
535 *
536 *--*/
537 NTSTATUS
538 NTAPI
539 CsrParseServerCommandLine(IN ULONG ArgumentCount,
540 IN PCHAR Arguments[])
541 {
542 NTSTATUS Status;
543 PCHAR ParameterName = NULL, ParameterValue = NULL, EntryPoint, ServerString;
544 ULONG i, DllIndex;
545 ANSI_STRING AnsiString;
546 OBJECT_ATTRIBUTES ObjectAttributes;
547
548 /* Set the Defaults */
549 CsrTotalPerProcessDataLength = 0;
550 CsrObjectDirectory = NULL;
551 CsrMaxApiRequestThreads = 16;
552
553 /* Save our Session ID, and create a Directory for it */
554 SessionId = NtCurrentPeb()->SessionId;
555 Status = CsrCreateSessionObjectDirectory(SessionId);
556 if (!NT_SUCCESS(Status))
557 {
558 DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
559 Status);
560
561 /* It's not fatal if the session ID isn't zero */
562 if (SessionId != 0) return Status;
563 ASSERT(NT_SUCCESS(Status));
564 }
565
566 /* Loop through every argument */
567 for (i = 1; i < ArgumentCount; i++)
568 {
569 /* Split Name and Value */
570 ParameterName = Arguments[i];
571 ParameterValue = NULL;
572 ParameterValue = strchr(ParameterName, '=');
573 if (ParameterValue) *ParameterValue++ = ANSI_NULL;
574 DPRINT1("Name=%s, Value=%s\n", ParameterName, ParameterValue);
575
576 /* Check for Object Directory */
577 if (_stricmp(ParameterName, "ObjectDirectory") == 0)
578 {
579 /* Check if a session ID is specified */
580 if (SessionId != 0)
581 {
582 DPRINT1("Sessions not yet implemented\n");
583 ASSERT(SessionId);
584 }
585
586 /* Initialize the directory name */
587 RtlInitAnsiString(&AnsiString, ParameterValue);
588 Status = RtlAnsiStringToUnicodeString(&CsrDirectoryName,
589 &AnsiString,
590 TRUE);
591 ASSERT(NT_SUCCESS(Status) || SessionId != 0);
592 if (!NT_SUCCESS(Status)) return Status;
593
594 /* Create it */
595 InitializeObjectAttributes(&ObjectAttributes,
596 &CsrDirectoryName,
597 OBJ_OPENIF | OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
598 NULL,
599 NULL);
600 Status = NtCreateDirectoryObject(&CsrObjectDirectory,
601 DIRECTORY_ALL_ACCESS,
602 &ObjectAttributes);
603 if (!NT_SUCCESS(Status)) return Status;
604
605 /* Secure it */
606 Status = CsrSetDirectorySecurity(CsrObjectDirectory);
607 if (!NT_SUCCESS(Status)) return Status;
608 }
609 else if (_stricmp(ParameterName, "SubSystemType") == 0)
610 {
611 /* Ignored */
612 }
613 else if (_stricmp(ParameterName, "MaxRequestThreads") == 0)
614 {
615 Status = RtlCharToInteger(ParameterValue,
616 0,
617 &CsrMaxApiRequestThreads);
618 }
619 else if (_stricmp(ParameterName, "RequestThreads") == 0)
620 {
621 /* Ignored */
622 Status = STATUS_SUCCESS;
623 }
624 else if (_stricmp(ParameterName, "ProfileControl") == 0)
625 {
626 /* Ignored */
627 }
628 else if (_stricmp(ParameterName, "SharedSection") == 0)
629 {
630 /* Create the Section */
631 Status = CsrSrvCreateSharedSection(ParameterValue);
632 if (!NT_SUCCESS(Status))
633 {
634 DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
635 ParameterName, ParameterValue, Status);
636 return Status;
637 }
638
639 /* Load us */
640 Status = CsrLoadServerDll("CSRSS" /* "CSRSRV" */, NULL, CSRSRV_SERVERDLL_INDEX);
641 }
642 else if (_stricmp(ParameterName, "ServerDll") == 0)
643 {
644 /* Loop the command line */
645 EntryPoint = NULL;
646 Status = STATUS_INVALID_PARAMETER;
647 ServerString = ParameterValue;
648 while (*ServerString)
649 {
650 /* Check for the Entry Point */
651 if ((*ServerString == ':') && (!EntryPoint))
652 {
653 /* Found it. Add a nullchar and save it */
654 *ServerString++ = ANSI_NULL;
655 EntryPoint = ServerString;
656 }
657
658 /* Check for the Dll Index */
659 if (*ServerString++ == ',') break;
660 }
661
662 /* Did we find something to load? */
663 if (!*ServerString)
664 {
665 DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
666 ParameterValue, Status);
667 return Status;
668 }
669
670 /* Convert it to a ULONG */
671 Status = RtlCharToInteger(ServerString, 10, &DllIndex);
672
673 /* Add a null char if it was valid */
674 if (NT_SUCCESS(Status)) ServerString[-1] = ANSI_NULL;
675
676 /* Load it */
677 if (CsrDebug & 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue, EntryPoint);
678 Status = CsrLoadServerDll(ParameterValue, EntryPoint, DllIndex);
679 if (!NT_SUCCESS(Status))
680 {
681 DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
682 ParameterValue, Status);
683 return Status;
684 }
685 }
686 else if (_stricmp(ParameterName, "Windows") == 0)
687 {
688 /* Ignored */
689 // Check whether we want to start in pure GUI or pure CLI.
690 }
691 else
692 {
693 /* Invalid parameter on the command line */
694 Status = STATUS_INVALID_PARAMETER;
695 }
696 }
697
698 /* Return status */
699 return Status;
700 }
701
702 /*++
703 * @name CsrInitCsrRootProcess
704 *
705 * The CsrInitCsrRootProcess routine further initializes the CSR Root Process
706 * created by CsrInitializeProcessStructure, by allocating and initializing
707 * per-process data for each Server DLL.
708 *
709 * @param None.
710 *
711 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
712 *
713 * @remarks None.
714 *
715 *--*/
716 NTSTATUS
717 NTAPI
718 CsrInitCsrRootProcess(VOID)
719 {
720 PVOID ProcessData;
721 PCSR_SERVER_DLL ServerDll;
722 ULONG i = 0;
723
724 /* All Server DLLs are now loaded, allocate a heap for the Root Process */
725 ProcessData = RtlAllocateHeap(CsrHeap,
726 HEAP_ZERO_MEMORY,
727 CsrTotalPerProcessDataLength);
728 if (!ProcessData)
729 {
730 DPRINT1("CSRSRV:%s: RtlAllocateHeap failed (Status=%08lx)\n",
731 __FUNCTION__, STATUS_NO_MEMORY);
732 return STATUS_NO_MEMORY;
733 }
734
735 /*
736 * Our Root Process was never officially initialized,
737 * so write the data for each Server DLL manually.
738 */
739
740 /* Loop every DLL */
741 for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
742 {
743 /* Get the current Server */
744 ServerDll = CsrLoadedServerDll[i];
745
746 /* Is it loaded, and does it have per process data? */
747 if (ServerDll && ServerDll->SizeOfProcessData)
748 {
749 /* It does, give it part of our allocated heap */
750 CsrRootProcess->ServerData[i] = ProcessData;
751
752 /* Move to the next heap position */
753 ProcessData = (PVOID)((ULONG_PTR)ProcessData +
754 ServerDll->SizeOfProcessData);
755 }
756 else
757 {
758 /* Nothing for this Server DLL */
759 CsrRootProcess->ServerData[i] = NULL;
760 }
761 }
762
763 /* Now initialize the Root Process manually as well */
764 for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
765 {
766 /* Get the current Server */
767 ServerDll = CsrLoadedServerDll[i];
768
769 /* Is it loaded, and does it a callback for new processes? */
770 if (ServerDll && ServerDll->NewProcessCallback)
771 {
772 /* Call the callback */
773 ServerDll->NewProcessCallback(NULL, CsrRootProcess);
774 }
775 }
776
777 return STATUS_SUCCESS;
778 }
779
780 /*++
781 * @name CsrCreateLocalSystemSD
782 *
783 * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
784 * the local account with PORT_ALL_ACCESS.
785 *
786 * @param LocalSystemSd
787 * Pointer to a pointer to the security descriptor to create.
788 *
789 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
790 *
791 * @remarks None.
792 *
793 *--*/
794 NTSTATUS
795 NTAPI
796 CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR *LocalSystemSd)
797 {
798 SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
799 PSID SystemSid;
800 ULONG Length;
801 PSECURITY_DESCRIPTOR SystemSd;
802 PACL Dacl;
803 NTSTATUS Status;
804
805 /* Initialize the System SID */
806 RtlAllocateAndInitializeSid(&NtSidAuthority, 1,
807 SECURITY_LOCAL_SYSTEM_RID,
808 0, 0, 0, 0, 0, 0, 0,
809 &SystemSid);
810
811 /* Get the length of the SID */
812 Length = RtlLengthSid(SystemSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE);
813
814 /* Allocate a buffer for the Security Descriptor, with SID and DACL */
815 SystemSd = RtlAllocateHeap(CsrHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
816
817 /* Set the pointer to the DACL */
818 Dacl = (PACL)((ULONG_PTR)SystemSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
819
820 /* Now create the SD itself */
821 Status = RtlCreateSecurityDescriptor(SystemSd, SECURITY_DESCRIPTOR_REVISION);
822 if (!NT_SUCCESS(Status)) goto Quit;
823
824 /* Create the DACL for it */
825 RtlCreateAcl(Dacl, Length, ACL_REVISION2);
826
827 /* Create the ACE */
828 Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PORT_ALL_ACCESS, SystemSid);
829 if (!NT_SUCCESS(Status)) goto Quit;
830
831 /* Clear the DACL in the SD */
832 Status = RtlSetDaclSecurityDescriptor(SystemSd, TRUE, Dacl, FALSE);
833 if (!NT_SUCCESS(Status)) goto Quit;
834
835 Quit:
836 if (!NT_SUCCESS(Status))
837 {
838 RtlFreeHeap(CsrHeap, 0, SystemSd);
839 SystemSd = NULL;
840 }
841
842 /* Free the SID and return*/
843 RtlFreeSid(SystemSid);
844 *LocalSystemSd = SystemSd;
845 return Status;
846 }
847
848 /*++
849 * @name CsrSbApiPortInitialize
850 *
851 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
852 * communications with the Session Manager (SM) and initializes the static
853 * thread that will handle connection requests and APIs.
854 *
855 * @param None
856 *
857 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
858 *
859 * @remarks None.
860 *
861 *--*/
862 NTSTATUS
863 NTAPI
864 CsrSbApiPortInitialize(VOID)
865 {
866 ULONG Size;
867 PSECURITY_DESCRIPTOR PortSd;
868 OBJECT_ATTRIBUTES ObjectAttributes;
869 NTSTATUS Status;
870 HANDLE hRequestThread;
871 CLIENT_ID ClientId;
872
873 /* Calculate how much space we'll need for the Port Name */
874 Size = CsrDirectoryName.Length + sizeof(SB_PORT_NAME) + sizeof(WCHAR);
875
876 /* Create the buffer for it */
877 CsrSbApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
878 if (!CsrSbApiPortName.Buffer) return STATUS_NO_MEMORY;
879
880 /* Setup the rest of the empty string */
881 CsrSbApiPortName.Length = 0;
882 CsrSbApiPortName.MaximumLength = (USHORT)Size;
883
884 /* Now append the full port name */
885 RtlAppendUnicodeStringToString(&CsrSbApiPortName, &CsrDirectoryName);
886 RtlAppendUnicodeToString(&CsrSbApiPortName, UNICODE_PATH_SEP);
887 RtlAppendUnicodeToString(&CsrSbApiPortName, SB_PORT_NAME);
888 if (CsrDebug & 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName);
889
890 /* Create Security Descriptor for this Port */
891 Status = CsrCreateLocalSystemSD(&PortSd);
892 if (!NT_SUCCESS(Status)) return Status;
893
894 /* Initialize the Attributes */
895 InitializeObjectAttributes(&ObjectAttributes,
896 &CsrSbApiPortName,
897 0,
898 NULL,
899 PortSd);
900
901 /* Create the Port Object */
902 Status = NtCreatePort(&CsrSbApiPort,
903 &ObjectAttributes,
904 sizeof(SB_CONNECTION_INFO),
905 sizeof(SB_API_MSG),
906 32 * sizeof(SB_API_MSG));
907 if (PortSd) RtlFreeHeap(CsrHeap, 0, PortSd);
908
909 if (NT_SUCCESS(Status))
910 {
911 /* Create the Thread to handle the API Requests */
912 Status = RtlCreateUserThread(NtCurrentProcess(),
913 NULL,
914 TRUE,
915 0,
916 0,
917 0,
918 (PVOID)CsrSbApiRequestThread,
919 NULL,
920 &hRequestThread,
921 &ClientId);
922 if (NT_SUCCESS(Status))
923 {
924 /* Add it as a Static Server Thread */
925 CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(hRequestThread,
926 &ClientId,
927 0);
928
929 /* Activate it */
930 Status = NtResumeThread(hRequestThread, NULL);
931 }
932 }
933
934 return Status;
935 }
936
937
938 /* PUBLIC FUNCTIONS ***********************************************************/
939
940 /*++
941 * @name CsrServerInitialization
942 * @implemented NT4
943 *
944 * The CsrServerInitialization routine is the native (not Server) entrypoint
945 * of this Server DLL. It serves as the entrypoint for CSRSS.
946 *
947 * @param ArgumentCount
948 * Number of arguments on the command line.
949 *
950 * @param Arguments
951 * Array of arguments from the command line.
952 *
953 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
954 *
955 * @remarks None.
956 *
957 *--*/
958 NTSTATUS
959 NTAPI
960 CsrServerInitialization(IN ULONG ArgumentCount,
961 IN PCHAR Arguments[])
962 {
963 NTSTATUS Status = STATUS_SUCCESS;
964
965 /* Cache System Basic Information so we don't always request it */
966 Status = NtQuerySystemInformation(SystemBasicInformation,
967 &CsrNtSysInfo,
968 sizeof(SYSTEM_BASIC_INFORMATION),
969 NULL);
970 if (!NT_SUCCESS(Status))
971 {
972 DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=0x%08lx)\n",
973 __FUNCTION__, Status);
974 return Status;
975 }
976
977 /* Save our Heap */
978 CsrHeap = RtlGetProcessHeap();
979
980 /* Set our Security Descriptor to protect the process */
981 Status = CsrSetProcessSecurity();
982 if (!NT_SUCCESS(Status))
983 {
984 DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=0x%08lx)\n",
985 __FUNCTION__, Status);
986 return Status;
987 }
988
989 /* Set up Session Support */
990 Status = CsrInitializeNtSessionList();
991 if (!NT_SUCCESS(Status))
992 {
993 DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=0x%08lx)\n",
994 __FUNCTION__, Status);
995 return Status;
996 }
997
998 /* Set up Process Support and allocate the CSR Root Process */
999 Status = CsrInitializeProcessStructure();
1000 if (!NT_SUCCESS(Status))
1001 {
1002 DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=0x%08lx)\n",
1003 __FUNCTION__, Status);
1004 return Status;
1005 }
1006
1007 /* Parse the command line */
1008 Status = CsrParseServerCommandLine(ArgumentCount, Arguments);
1009 if (!NT_SUCCESS(Status))
1010 {
1011 DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=0x%08lx)\n",
1012 __FUNCTION__, Status);
1013 return Status;
1014 }
1015
1016 /* Finish to initialize the CSR Root Process */
1017 Status = CsrInitCsrRootProcess();
1018 if (!NT_SUCCESS(Status))
1019 {
1020 DPRINT1("CSRSRV:%s: CsrInitCsrRootProcess failed (Status=0x%08lx)\n",
1021 __FUNCTION__, Status);
1022 return Status;
1023 }
1024
1025 /* Now initialize our API Port */
1026 Status = CsrApiPortInitialize();
1027 if (!NT_SUCCESS(Status))
1028 {
1029 DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=0x%08lx)\n",
1030 __FUNCTION__, Status);
1031 return Status;
1032 }
1033
1034 /* Initialize the API Port for SM communication */
1035 Status = CsrSbApiPortInitialize();
1036 if (!NT_SUCCESS(Status))
1037 {
1038 DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=0x%08lx)\n",
1039 __FUNCTION__, Status);
1040 return Status;
1041 }
1042
1043 /* We're all set! Connect to SM! */
1044 Status = SmConnectToSm(&CsrSbApiPortName,
1045 CsrSbApiPort,
1046 IMAGE_SUBSYSTEM_WINDOWS_GUI,
1047 &CsrSmApiPort);
1048 if (!NT_SUCCESS(Status))
1049 {
1050 DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=0x%08lx)\n",
1051 __FUNCTION__, Status);
1052 return Status;
1053 }
1054
1055 /* Have us handle Hard Errors */
1056 Status = NtSetDefaultHardErrorPort(CsrApiPort);
1057 if (!NT_SUCCESS(Status))
1058 {
1059 DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=0x%08lx)\n",
1060 __FUNCTION__, Status);
1061 return Status;
1062 }
1063
1064 /* Return status */
1065 return Status;
1066 }
1067
1068 /*++
1069 * @name CsrPopulateDosDevices
1070 * @unimplemented NT5.1
1071 *
1072 * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
1073 * to populate the Dos Devices Object Directory for the session.
1074 *
1075 * @param None.
1076 *
1077 * @return None.
1078 *
1079 * @remarks None.
1080 *
1081 *--*/
1082 VOID
1083 NTAPI
1084 CsrPopulateDosDevices(VOID)
1085 {
1086 DPRINT1("Deprecated API in r55585.\n");
1087 return;
1088 }
1089
1090 BOOL
1091 NTAPI
1092 DllMain(IN HINSTANCE hInstanceDll,
1093 IN DWORD dwReason,
1094 IN LPVOID lpReserved)
1095 {
1096 /* We don't do much */
1097 UNREFERENCED_PARAMETER(hInstanceDll);
1098 UNREFERENCED_PARAMETER(dwReason);
1099 UNREFERENCED_PARAMETER(lpReserved);
1100
1101 return TRUE;
1102 }
1103
1104 /* EOF */