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