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