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