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