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