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