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