Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensminit.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Windows-Compatible Session Manager 00003 * LICENSE: BSD 2-Clause License 00004 * FILE: base/system/smss/smss.c 00005 * PURPOSE: Main SMSS Code 00006 * PROGRAMMERS: Alex Ionescu 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include "smss.h" 00012 #define NDEBUG 00013 #include "debug.h" 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 UNICODE_STRING SmpSubsystemName, PosixName, Os2Name; 00018 LIST_ENTRY SmpBootExecuteList, SmpSetupExecuteList, SmpPagingFileList; 00019 LIST_ENTRY SmpDosDevicesList, SmpFileRenameList, SmpKnownDllsList; 00020 LIST_ENTRY SmpExcludeKnownDllsList, SmpSubSystemList, SmpSubSystemsToLoad; 00021 LIST_ENTRY SmpSubSystemsToDefer, SmpExecuteList, NativeProcessList; 00022 00023 PVOID SmpHeap; 00024 ULONG SmBaseTag; 00025 HANDLE SmpDebugPort, SmpDosDevicesObjectDirectory; 00026 PWCHAR SmpDefaultEnvironment, SmpDefaultLibPathBuffer; 00027 UNICODE_STRING SmpKnownDllPath, SmpDefaultLibPath; 00028 ULONG SmpCalledConfigEnv; 00029 00030 ULONG SmpInitProgressByLine; 00031 NTSTATUS SmpInitReturnStatus; 00032 PVOID SmpInitLastCall; 00033 00034 SECURITY_DESCRIPTOR SmpPrimarySDBody, SmpLiberalSDBody, SmpKnownDllsSDBody; 00035 SECURITY_DESCRIPTOR SmpApiPortSDBody; 00036 PISECURITY_DESCRIPTOR SmpPrimarySecurityDescriptor, SmpLiberalSecurityDescriptor; 00037 PISECURITY_DESCRIPTOR SmpKnownDllsSecurityDescriptor, SmpApiPortSecurityDescriptor; 00038 00039 ULONG SmpAllowProtectedRenames, SmpProtectionMode = 1; 00040 BOOLEAN MiniNTBoot; 00041 00042 #define SMSS_CHECKPOINT(x, y) \ 00043 { \ 00044 SmpInitProgressByLine = __LINE__; \ 00045 SmpInitReturnStatus = (y); \ 00046 SmpInitLastCall = (x); \ 00047 } 00048 00049 /* REGISTRY CONFIGURATION *****************************************************/ 00050 00051 NTSTATUS 00052 NTAPI 00053 SmpSaveRegistryValue(IN PLIST_ENTRY ListAddress, 00054 IN PWSTR Name, 00055 IN PWCHAR Value, 00056 IN BOOLEAN Flags) 00057 { 00058 PSMP_REGISTRY_VALUE RegEntry; 00059 UNICODE_STRING NameString, ValueString; 00060 ANSI_STRING AnsiValueString; 00061 PLIST_ENTRY NextEntry; 00062 00063 /* Convert to unicode strings */ 00064 RtlInitUnicodeString(&NameString, Name); 00065 RtlInitUnicodeString(&ValueString, Value); 00066 00067 /* In case this is the first value, initialize a new list/structure */ 00068 RegEntry = NULL; 00069 00070 /* Check if we should do a duplicate check */ 00071 if (Flags) 00072 { 00073 /* Loop the current list */ 00074 NextEntry = ListAddress->Flink; 00075 while (NextEntry != ListAddress) 00076 { 00077 /* Get each entry */ 00078 RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry); 00079 00080 /* Check if the value name matches */ 00081 if (!RtlCompareUnicodeString(&RegEntry->Name, &NameString, TRUE)) 00082 { 00083 /* Check if the value is the exact same thing */ 00084 if (!RtlCompareUnicodeString(&RegEntry->Value, &ValueString, TRUE)) 00085 { 00086 /* Fail -- the same setting is being set twice */ 00087 return STATUS_OBJECT_NAME_EXISTS; 00088 } 00089 00090 /* We found the list, and this isn't a duplicate value */ 00091 break; 00092 } 00093 00094 /* This wasn't a match, keep going */ 00095 NextEntry = NextEntry->Flink; 00096 RegEntry = NULL; 00097 } 00098 } 00099 00100 /* Are we adding on, or creating a new entry */ 00101 if (!RegEntry) 00102 { 00103 /* A new entry -- allocate it */ 00104 RegEntry = RtlAllocateHeap(RtlGetProcessHeap(), 00105 SmBaseTag, 00106 NameString.MaximumLength + 00107 sizeof(SMP_REGISTRY_VALUE)); 00108 if (!RegEntry) return STATUS_NO_MEMORY; 00109 00110 /* Initialize the list and set all values to NULL */ 00111 InitializeListHead(&RegEntry->Entry); 00112 RegEntry->AnsiValue = NULL; 00113 RegEntry->Value.Buffer = NULL; 00114 00115 /* Copy and initialize the value name */ 00116 RegEntry->Name.Buffer = (PWCHAR)(RegEntry + 1); 00117 RegEntry->Name.Length = NameString.Length; 00118 RegEntry->Name.MaximumLength = NameString.MaximumLength; 00119 RtlCopyMemory(RegEntry->Name.Buffer, 00120 NameString.Buffer, 00121 NameString.MaximumLength); 00122 00123 /* Add this entry into the list */ 00124 InsertTailList(ListAddress, &RegEntry->Entry); 00125 } 00126 00127 /* Did we have an old value buffer? */ 00128 if (RegEntry->Value.Buffer) 00129 { 00130 /* Free it */ 00131 ASSERT(RegEntry->Value.Length != 0); 00132 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer); 00133 } 00134 00135 /* Is there no value associated? */ 00136 if (!Value) 00137 { 00138 /* We're done here */ 00139 RtlInitUnicodeString(&RegEntry->Value, NULL); 00140 return STATUS_SUCCESS; 00141 } 00142 00143 /* There is a value, so allocate a buffer for it */ 00144 RegEntry->Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 00145 SmBaseTag, 00146 ValueString.MaximumLength); 00147 if (!RegEntry->Value.Buffer) 00148 { 00149 /* Out of memory, undo */ 00150 RemoveEntryList(&RegEntry->Entry); 00151 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry); 00152 return STATUS_NO_MEMORY; 00153 } 00154 00155 /* Copy the value into the entry */ 00156 RegEntry->Value.Length = ValueString.Length; 00157 RegEntry->Value.MaximumLength = ValueString.MaximumLength; 00158 RtlCopyMemory(RegEntry->Value.Buffer, 00159 ValueString.Buffer, 00160 ValueString.MaximumLength); 00161 00162 /* Now allocate memory for an ANSI copy of it */ 00163 RegEntry->AnsiValue = RtlAllocateHeap(RtlGetProcessHeap(), 00164 SmBaseTag, 00165 (ValueString.Length / sizeof(WCHAR)) + 00166 sizeof(ANSI_NULL)); 00167 if (!RegEntry->AnsiValue) 00168 { 00169 /* Out of memory, undo */ 00170 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer); 00171 RemoveEntryList(&RegEntry->Entry); 00172 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry); 00173 return STATUS_NO_MEMORY; 00174 } 00175 00176 /* Convert the Unicode value string and return success */ 00177 RtlInitEmptyAnsiString(&AnsiValueString, 00178 RegEntry->AnsiValue, 00179 (ValueString.Length / sizeof(WCHAR)) + 00180 sizeof(ANSI_NULL)); 00181 RtlUnicodeStringToAnsiString(&AnsiValueString, &ValueString, FALSE); 00182 return STATUS_SUCCESS; 00183 } 00184 00185 PSMP_REGISTRY_VALUE 00186 NTAPI 00187 SmpFindRegistryValue(IN PLIST_ENTRY List, 00188 IN PWSTR ValueName) 00189 { 00190 PSMP_REGISTRY_VALUE RegEntry; 00191 UNICODE_STRING ValueString; 00192 PLIST_ENTRY NextEntry; 00193 00194 /* Initialize the value name sting */ 00195 RtlInitUnicodeString(&ValueString, ValueName); 00196 00197 /* Loop the list */ 00198 NextEntry = List->Flink; 00199 while (NextEntry != List) 00200 { 00201 /* Get each entry */ 00202 RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry); 00203 00204 /* Check if the value name matches */ 00205 if (!RtlCompareUnicodeString(&RegEntry->Name, &ValueString, TRUE)) break; 00206 00207 /* It doesn't, move on */ 00208 NextEntry = NextEntry->Flink; 00209 } 00210 00211 /* If we looped back, return NULL, otherwise return the entry we found */ 00212 if (NextEntry == List) RegEntry = NULL; 00213 return RegEntry; 00214 } 00215 00216 NTSTATUS 00217 NTAPI 00218 SmpConfigureProtectionMode(IN PWSTR ValueName, 00219 IN ULONG ValueType, 00220 IN PVOID ValueData, 00221 IN ULONG ValueLength, 00222 IN PVOID Context, 00223 IN PVOID EntryContext) 00224 { 00225 /* Make sure the value is valid */ 00226 if (ValueLength == sizeof(ULONG)) 00227 { 00228 /* Read it */ 00229 SmpProtectionMode = *(PULONG)ValueData; 00230 } 00231 else 00232 { 00233 /* Default is to protect stuff */ 00234 SmpProtectionMode = 1; 00235 } 00236 00237 /* Recreate the security descriptors to take into account security mode */ 00238 SmpCreateSecurityDescriptors(FALSE); 00239 DPRINT("SmpProtectionMode: %d\n", SmpProtectionMode); 00240 return STATUS_SUCCESS; 00241 } 00242 00243 NTSTATUS 00244 NTAPI 00245 SmpConfigureAllowProtectedRenames(IN PWSTR ValueName, 00246 IN ULONG ValueType, 00247 IN PVOID ValueData, 00248 IN ULONG ValueLength, 00249 IN PVOID Context, 00250 IN PVOID EntryContext) 00251 { 00252 /* Make sure the value is valid */ 00253 if (ValueLength == sizeof(ULONG)) 00254 { 00255 /* Read it */ 00256 SmpAllowProtectedRenames = *(PULONG)ValueData; 00257 } 00258 else 00259 { 00260 /* Default is to not allow protected renames */ 00261 SmpAllowProtectedRenames = 0; 00262 } 00263 00264 DPRINT("SmpAllowProtectedRenames: %d\n", SmpAllowProtectedRenames); 00265 return STATUS_SUCCESS; 00266 } 00267 00268 NTSTATUS 00269 NTAPI 00270 SmpConfigureObjectDirectories(IN PWSTR ValueName, 00271 IN ULONG ValueType, 00272 IN PVOID ValueData, 00273 IN ULONG ValueLength, 00274 IN PVOID Context, 00275 IN PVOID EntryContext) 00276 { 00277 PISECURITY_DESCRIPTOR SecDescriptor; 00278 NTSTATUS Status; 00279 OBJECT_ATTRIBUTES ObjectAttributes; 00280 HANDLE DirHandle; 00281 UNICODE_STRING RpcString, WindowsString, SearchString; 00282 PWCHAR SourceString = ValueData; 00283 00284 /* Initialize the two strings we will be looking for */ 00285 RtlInitUnicodeString(&RpcString, L"\\RPC Control"); 00286 RtlInitUnicodeString(&WindowsString, L"\\Windows"); 00287 00288 /* Loop the registry data we received */ 00289 while (*SourceString) 00290 { 00291 /* Assume primary SD for most objects */ 00292 RtlInitUnicodeString(&SearchString, SourceString); 00293 SecDescriptor = SmpPrimarySecurityDescriptor; 00294 00295 /* But for these two always set the liberal descriptor */ 00296 if ((RtlEqualUnicodeString(&SearchString, &RpcString, TRUE)) || 00297 (RtlEqualUnicodeString(&SearchString, &WindowsString, TRUE))) 00298 { 00299 SecDescriptor = SmpLiberalSecurityDescriptor; 00300 } 00301 00302 /* Create the requested directory with the requested descriptor */ 00303 InitializeObjectAttributes(&ObjectAttributes, 00304 &SearchString, 00305 OBJ_CASE_INSENSITIVE | 00306 OBJ_OPENIF | 00307 OBJ_PERMANENT, 00308 NULL, 00309 SecDescriptor); 00310 DPRINT("Creating: %wZ directory\n", &SearchString); 00311 Status = NtCreateDirectoryObject(&DirHandle, 00312 DIRECTORY_ALL_ACCESS, 00313 &ObjectAttributes); 00314 if (!NT_SUCCESS(Status)) 00315 { 00316 /* Failure case */ 00317 DPRINT1("SMSS: Unable to create %wZ object directory - Status == %lx\n", 00318 &SearchString, Status); 00319 } 00320 else 00321 { 00322 /* It worked, now close the handle */ 00323 NtClose(DirHandle); 00324 } 00325 00326 /* Move to the next requested object */ 00327 while (*SourceString++); 00328 } 00329 00330 /* All done */ 00331 return STATUS_SUCCESS; 00332 } 00333 00334 NTSTATUS 00335 NTAPI 00336 SmpConfigureMemoryMgmt(IN PWSTR ValueName, 00337 IN ULONG ValueType, 00338 IN PVOID ValueData, 00339 IN ULONG ValueLength, 00340 IN PVOID Context, 00341 IN PVOID EntryContext) 00342 { 00343 /* Save this is into a list */ 00344 return SmpSaveRegistryValue(EntryContext, ValueData, NULL, TRUE); 00345 } 00346 00347 NTSTATUS 00348 NTAPI 00349 SmpConfigureFileRenames(IN PWSTR ValueName, 00350 IN ULONG ValueType, 00351 IN PVOID ValueData, 00352 IN ULONG ValueLength, 00353 IN PVOID Context, 00354 IN PVOID EntryContext) 00355 { 00356 NTSTATUS Status; 00357 static PWCHAR Canary; 00358 00359 /* Check if this is the second call */ 00360 if (Canary) 00361 { 00362 /* Save the data into the list */ 00363 DPRINT1("Renamed file: %S-%S\n", Canary, ValueData); 00364 Status = SmpSaveRegistryValue(EntryContext, Canary, ValueData, FALSE); 00365 Canary = 0; 00366 } 00367 else 00368 { 00369 /* This it the first call, do nothing until we get the second call */ 00370 Canary = ValueData; 00371 Status = STATUS_SUCCESS; 00372 } 00373 00374 /* Return the status */ 00375 return Status; 00376 } 00377 00378 NTSTATUS 00379 NTAPI 00380 SmpConfigureExcludeKnownDlls(IN PWSTR ValueName, 00381 IN ULONG ValueType, 00382 IN PVOID ValueData, 00383 IN ULONG ValueLength, 00384 IN PVOID Context, 00385 IN PVOID EntryContext) 00386 { 00387 PWCHAR DllName; 00388 NTSTATUS Status; 00389 00390 /* Make sure the value type is valid */ 00391 if ((ValueType == REG_MULTI_SZ) || (ValueType == REG_SZ)) 00392 { 00393 /* Keep going for each DLL in the list */ 00394 DllName = ValueData; 00395 while (*DllName) 00396 { 00397 /* Add this to the linked list */ 00398 DPRINT("Excluded DLL: %S\n", DllName); 00399 Status = SmpSaveRegistryValue(EntryContext, DllName, NULL, TRUE); 00400 00401 /* Bail out on failure or if only one DLL name was present */ 00402 if (!(NT_SUCCESS(Status)) || (ValueType == REG_SZ)) return Status; 00403 00404 /* Otherwise, move to the next DLL name */ 00405 while (*DllName++); 00406 } 00407 } 00408 00409 /* All done */ 00410 return STATUS_SUCCESS; 00411 } 00412 00413 NTSTATUS 00414 NTAPI 00415 SmpConfigureDosDevices(IN PWSTR ValueName, 00416 IN ULONG ValueType, 00417 IN PVOID ValueData, 00418 IN ULONG ValueLength, 00419 IN PVOID Context, 00420 IN PVOID EntryContext) 00421 { 00422 /* Save into linked list */ 00423 return SmpSaveRegistryValue(EntryContext, ValueName, ValueData, TRUE); 00424 } 00425 00426 NTSTATUS 00427 NTAPI 00428 SmpInitializeKnownDllPath(IN PUNICODE_STRING DllPath, 00429 IN PWCHAR Buffer, 00430 IN ULONG Length) 00431 { 00432 NTSTATUS Status; 00433 00434 /* Allocate the buffer */ 00435 DllPath->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), SmBaseTag, Length); 00436 if (DllPath->Buffer) 00437 { 00438 /* Fill out the rest of the string */ 00439 DllPath->MaximumLength = (USHORT)Length; 00440 DllPath->Length = (USHORT)Length - sizeof(UNICODE_NULL); 00441 00442 /* Copy the actual path and return success */ 00443 RtlCopyMemory(DllPath->Buffer, Buffer, Length); 00444 Status = STATUS_SUCCESS; 00445 } 00446 else 00447 { 00448 /* Fail with out of memory code */ 00449 Status = STATUS_NO_MEMORY; 00450 } 00451 00452 /* Return result */ 00453 return Status; 00454 } 00455 00456 NTSTATUS 00457 NTAPI 00458 SmpConfigureKnownDlls(IN PWSTR ValueName, 00459 IN ULONG ValueType, 00460 IN PVOID ValueData, 00461 IN ULONG ValueLength, 00462 IN PVOID Context, 00463 IN PVOID EntryContext) 00464 { 00465 /* Check which value is being set */ 00466 if (_wcsicmp(ValueName, L"DllDirectory")) 00467 { 00468 /* Add to the linked list -- this is a file */ 00469 return SmpSaveRegistryValue(EntryContext, ValueName, ValueData, TRUE); 00470 } 00471 00472 /* This is the directory, initialize it */ 00473 DPRINT("KnownDll Path: %S\n", ValueData); 00474 return SmpInitializeKnownDllPath(&SmpKnownDllPath, ValueData, ValueLength); 00475 } 00476 00477 NTSTATUS 00478 NTAPI 00479 SmpConfigureEnvironment(IN PWSTR ValueName, 00480 IN ULONG ValueType, 00481 IN PVOID ValueData, 00482 IN ULONG ValueLength, 00483 IN PVOID Context, 00484 IN PVOID EntryContext) 00485 { 00486 NTSTATUS Status; 00487 UNICODE_STRING ValueString, DataString; 00488 00489 /* Convert the strings into UNICODE_STRING and set the variable defined */ 00490 RtlInitUnicodeString(&ValueString, ValueName); 00491 RtlInitUnicodeString(&DataString, ValueData); 00492 DPRINT("Setting %wZ = %wZ\n", &ValueString, &DataString); 00493 Status = RtlSetEnvironmentVariable(0, &ValueString, &DataString); 00494 if (!NT_SUCCESS(Status)) 00495 { 00496 DPRINT1("SMSS: 'SET %wZ = %wZ' failed - Status == %lx\n", 00497 &ValueString, &DataString, Status); 00498 return Status; 00499 } 00500 00501 /* Check if the path is being set, and wait for the second instantiation */ 00502 if (!(_wcsicmp(ValueName, L"Path")) && (++SmpCalledConfigEnv == 2)) 00503 { 00504 /* Allocate the path buffer */ 00505 SmpDefaultLibPathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 00506 SmBaseTag, 00507 ValueLength); 00508 if (!SmpDefaultLibPathBuffer) return STATUS_NO_MEMORY; 00509 00510 /* Copy the data into it and create the UNICODE_STRING to hold it */ 00511 RtlCopyMemory(SmpDefaultLibPathBuffer, ValueData, ValueLength); 00512 RtlInitUnicodeString(&SmpDefaultLibPath, SmpDefaultLibPathBuffer); 00513 } 00514 00515 /* All good */ 00516 return STATUS_SUCCESS; 00517 } 00518 00519 NTSTATUS 00520 NTAPI 00521 SmpConfigureSubSystems(IN PWSTR ValueName, 00522 IN ULONG ValueType, 00523 IN PVOID ValueData, 00524 IN ULONG ValueLength, 00525 IN PVOID Context, 00526 IN PVOID EntryContext) 00527 { 00528 PSMP_REGISTRY_VALUE RegEntry; 00529 PWCHAR SubsystemName; 00530 00531 /* Is this a required or optional subsystem */ 00532 if ((_wcsicmp(ValueName, L"Required")) && 00533 (_wcsicmp(ValueName, L"Optional"))) 00534 { 00535 /* It isn't, is this the PSI flag? */ 00536 if ((_wcsicmp(ValueName, L"PosixSingleInstance")) || 00537 (ValueType != REG_DWORD)) 00538 { 00539 /* It isn't, must be a subsystem entry, add it to the list */ 00540 DPRINT("Subsystem entry: %S-%S\n", ValueName, ValueData); 00541 return SmpSaveRegistryValue(EntryContext, ValueName, ValueData, TRUE); 00542 } 00543 00544 /* This was the PSI flag, save it and exit */ 00545 RegPosixSingleInstance = TRUE; 00546 return STATUS_SUCCESS; 00547 } 00548 00549 /* This should be one of the required/optional lists. Is the type valid? */ 00550 if (ValueType == REG_MULTI_SZ) 00551 { 00552 /* It is, get the first subsystem */ 00553 SubsystemName = ValueData; 00554 while (*SubsystemName) 00555 { 00556 /* We should have already put it into the list when we found it */ 00557 DPRINT("Found subsystem: %S\n", SubsystemName); 00558 RegEntry = SmpFindRegistryValue(EntryContext, SubsystemName); 00559 if (!RegEntry) 00560 { 00561 /* This subsystem doesn't exist, so skip it */ 00562 DPRINT1("SMSS: Invalid subsystem name - %ws\n", SubsystemName); 00563 } 00564 else 00565 { 00566 /* Found it -- remove it from the main list */ 00567 RemoveEntryList(&RegEntry->Entry); 00568 00569 /* Figure out which list to put it in */ 00570 if (_wcsicmp(ValueName, L"Required")) 00571 { 00572 /* Put it into the optional list */ 00573 DPRINT("Optional\n"); 00574 InsertTailList(&SmpSubSystemsToDefer, &RegEntry->Entry); 00575 } 00576 else 00577 { 00578 /* Put it into the required list */ 00579 DPRINT("Required\n"); 00580 InsertTailList(&SmpSubSystemsToLoad, &RegEntry->Entry); 00581 } 00582 } 00583 00584 /* Move to the next name */ 00585 while (*SubsystemName++); 00586 } 00587 } 00588 00589 /* All done! */ 00590 return STATUS_SUCCESS; 00591 } 00592 00593 RTL_QUERY_REGISTRY_TABLE 00594 SmpRegistryConfigurationTable[] = 00595 { 00596 { 00597 SmpConfigureProtectionMode, 00598 0, 00599 L"ProtectionMode", 00600 NULL, 00601 REG_DWORD, 00602 NULL, 00603 0 00604 }, 00605 00606 { 00607 SmpConfigureAllowProtectedRenames, 00608 0, //RTL_QUERY_REGISTRY_DELETE, 00609 L"AllowProtectedRenames", 00610 NULL, 00611 REG_DWORD, 00612 NULL, 00613 0 00614 }, 00615 00616 { 00617 SmpConfigureObjectDirectories, 00618 0, 00619 L"ObjectDirectories", 00620 NULL, 00621 REG_MULTI_SZ, 00622 L"\\Windows\0\\RPC Control\0", 00623 0 00624 }, 00625 00626 { 00627 SmpConfigureMemoryMgmt, 00628 0, 00629 L"BootExecute", 00630 &SmpBootExecuteList, 00631 REG_NONE, 00632 NULL, 00633 0 00634 }, 00635 00636 { 00637 SmpConfigureMemoryMgmt, 00638 RTL_QUERY_REGISTRY_TOPKEY, 00639 L"SetupExecute", 00640 &SmpSetupExecuteList, 00641 REG_NONE, 00642 NULL, 00643 0 00644 }, 00645 00646 { 00647 SmpConfigureFileRenames, 00648 0, //RTL_QUERY_REGISTRY_DELETE, 00649 L"PendingFileRenameOperations", 00650 &SmpFileRenameList, 00651 REG_NONE, 00652 NULL, 00653 0 00654 }, 00655 00656 { 00657 SmpConfigureFileRenames, 00658 0, //RTL_QUERY_REGISTRY_DELETE, 00659 L"PendingFileRenameOperations2", 00660 &SmpFileRenameList, 00661 REG_NONE, 00662 NULL, 00663 0 00664 }, 00665 00666 { 00667 SmpConfigureExcludeKnownDlls, 00668 0, 00669 L"ExcludeFromKnownDlls", 00670 &SmpExcludeKnownDllsList, 00671 REG_MULTI_SZ, 00672 L"\0", 00673 0 00674 }, 00675 00676 { 00677 NULL, 00678 RTL_QUERY_REGISTRY_SUBKEY, 00679 L"Memory Management", 00680 NULL, 00681 REG_NONE, 00682 NULL, 00683 0 00684 }, 00685 00686 { 00687 SmpConfigureMemoryMgmt, 00688 0, 00689 L"PagingFiles", 00690 &SmpPagingFileList, 00691 REG_MULTI_SZ, 00692 L"?:\\pagefile.sys\0", 00693 0 00694 }, 00695 00696 { 00697 SmpConfigureDosDevices, 00698 RTL_QUERY_REGISTRY_SUBKEY, 00699 L"DOS Devices", 00700 &SmpDosDevicesList, 00701 REG_NONE, 00702 NULL, 00703 0 00704 }, 00705 00706 { 00707 SmpConfigureKnownDlls, 00708 RTL_QUERY_REGISTRY_SUBKEY, 00709 L"KnownDlls", 00710 &SmpKnownDllsList, 00711 REG_NONE, 00712 NULL, 00713 0 00714 }, 00715 00716 { 00717 SmpConfigureEnvironment, 00718 RTL_QUERY_REGISTRY_SUBKEY, 00719 L"Environment", 00720 NULL, 00721 REG_NONE, 00722 NULL, 00723 0 00724 }, 00725 00726 { 00727 SmpConfigureEnvironment, 00728 RTL_QUERY_REGISTRY_SUBKEY, 00729 L"Environment", 00730 NULL, 00731 REG_NONE, 00732 NULL, 00733 0 00734 }, 00735 00736 { 00737 SmpConfigureSubSystems, 00738 RTL_QUERY_REGISTRY_SUBKEY, 00739 L"SubSystems", 00740 &SmpSubSystemList, 00741 REG_NONE, 00742 NULL, 00743 0 00744 }, 00745 00746 { 00747 SmpConfigureSubSystems, 00748 RTL_QUERY_REGISTRY_NOEXPAND, 00749 L"Required", 00750 &SmpSubSystemList, 00751 REG_MULTI_SZ, 00752 L"Debug\0Windows\0", 00753 0 00754 }, 00755 00756 { 00757 SmpConfigureSubSystems, 00758 RTL_QUERY_REGISTRY_NOEXPAND, 00759 L"Optional", 00760 &SmpSubSystemList, 00761 REG_NONE, 00762 NULL, 00763 0 00764 }, 00765 00766 { 00767 SmpConfigureSubSystems, 00768 0, 00769 L"Kmode", 00770 &SmpSubSystemList, 00771 REG_NONE, 00772 NULL, 00773 0 00774 }, 00775 00776 { 00777 SmpConfigureMemoryMgmt, 00778 RTL_QUERY_REGISTRY_TOPKEY, 00779 L"Execute", 00780 &SmpExecuteList, 00781 REG_NONE, 00782 NULL, 00783 0 00784 }, 00785 00786 {0}, 00787 }; 00788 00789 /* FUNCTIONS ******************************************************************/ 00790 00791 VOID 00792 NTAPI 00793 SmpTranslateSystemPartitionInformation(VOID) 00794 { 00795 NTSTATUS Status; 00796 UNICODE_STRING UnicodeString, LinkTarget, SearchString, SystemPartition; 00797 OBJECT_ATTRIBUTES ObjectAttributes; 00798 HANDLE KeyHandle, LinkHandle; 00799 CHAR ValueBuffer[512 + sizeof(KEY_VALUE_PARTIAL_INFORMATION)]; 00800 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)ValueBuffer; 00801 ULONG Length, Context; 00802 CHAR DirInfoBuffer[512 + sizeof(OBJECT_DIRECTORY_INFORMATION)]; 00803 POBJECT_DIRECTORY_INFORMATION DirInfo = (PVOID)DirInfoBuffer; 00804 WCHAR LinkBuffer[MAX_PATH]; 00805 00806 /* Open the setup key */ 00807 RtlInitUnicodeString(&UnicodeString, L"\\Registry\\Machine\\System\\Setup"); 00808 InitializeObjectAttributes(&ObjectAttributes, 00809 &UnicodeString, 00810 OBJ_CASE_INSENSITIVE, 00811 NULL, 00812 NULL); 00813 Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); 00814 if (!NT_SUCCESS(Status)) 00815 { 00816 DPRINT1("SMSS: can't open system setup key for reading: 0x%x\n", Status); 00817 return; 00818 } 00819 00820 /* Query the system partition */ 00821 RtlInitUnicodeString(&UnicodeString, L"SystemPartition"); 00822 Status = NtQueryValueKey(KeyHandle, 00823 &UnicodeString, 00824 KeyValuePartialInformation, 00825 PartialInfo, 00826 sizeof(ValueBuffer), 00827 &Length); 00828 NtClose(KeyHandle); 00829 if (!NT_SUCCESS(Status)) 00830 { 00831 DPRINT1("SMSS: can't query SystemPartition value: 0x%x\n", Status); 00832 return; 00833 } 00834 00835 /* Initialize the system partition string string */ 00836 RtlInitUnicodeString(&SystemPartition, (PWCHAR)PartialInfo->Data); 00837 00838 /* Enumerate the directory looking for the symbolic link string */ 00839 RtlInitUnicodeString(&SearchString, L"SymbolicLink"); 00840 RtlInitEmptyUnicodeString(&LinkTarget, LinkBuffer, sizeof(LinkBuffer)); 00841 Status = NtQueryDirectoryObject(SmpDosDevicesObjectDirectory, 00842 DirInfo, 00843 sizeof(DirInfoBuffer), 00844 TRUE, 00845 TRUE, 00846 &Context, 00847 NULL); 00848 if (!NT_SUCCESS(Status)) 00849 { 00850 DPRINT1("SMSS: can't find drive letter for system partition\n"); 00851 return; 00852 } 00853 00854 /* Keep searching until we find it */ 00855 do 00856 { 00857 /* Is this it? */ 00858 if ((RtlEqualUnicodeString(&DirInfo->TypeName, &SearchString, TRUE)) && 00859 (DirInfo->Name.Length == 2 * sizeof(WCHAR)) && 00860 (DirInfo->Name.Buffer[1] == L':')) 00861 { 00862 /* Looks like we found it, open the link to get its target */ 00863 InitializeObjectAttributes(&ObjectAttributes, 00864 &DirInfo->Name, 00865 OBJ_CASE_INSENSITIVE, 00866 SmpDosDevicesObjectDirectory, 00867 NULL); 00868 Status = NtOpenSymbolicLinkObject(&LinkHandle, 00869 SYMBOLIC_LINK_ALL_ACCESS, 00870 &ObjectAttributes); 00871 if (NT_SUCCESS(Status)) 00872 { 00873 /* Open worked, query the target now */ 00874 Status = NtQuerySymbolicLinkObject(LinkHandle, 00875 &LinkTarget, 00876 NULL); 00877 NtClose(LinkHandle); 00878 00879 /* Check if it matches the string we had found earlier */ 00880 if ((NT_SUCCESS(Status)) && 00881 ((RtlEqualUnicodeString(&SystemPartition, 00882 &LinkTarget, 00883 TRUE)) || 00884 ((RtlPrefixUnicodeString(&SystemPartition, 00885 &LinkTarget, 00886 TRUE)) && 00887 (LinkTarget.Buffer[SystemPartition.Length / sizeof(WCHAR)] == L'\\')))) 00888 { 00889 /* All done */ 00890 break; 00891 } 00892 } 00893 } 00894 00895 /* Couldn't find it, try again */ 00896 Status = NtQueryDirectoryObject(SmpDosDevicesObjectDirectory, 00897 DirInfo, 00898 sizeof(DirInfoBuffer), 00899 TRUE, 00900 FALSE, 00901 &Context, 00902 NULL); 00903 } while (NT_SUCCESS(Status)); 00904 if (!NT_SUCCESS(Status)) 00905 { 00906 DPRINT1("SMSS: can't find drive letter for system partition\n"); 00907 return; 00908 } 00909 00910 /* Open the setup key again, for full access this time */ 00911 RtlInitUnicodeString(&UnicodeString, 00912 L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup"); 00913 InitializeObjectAttributes(&ObjectAttributes, 00914 &UnicodeString, 00915 OBJ_CASE_INSENSITIVE, 00916 NULL, 00917 NULL); 00918 Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); 00919 if (!NT_SUCCESS(Status)) 00920 { 00921 DPRINT1("SMSS: can't open software setup key for writing: 0x%x\n", 00922 Status); 00923 return; 00924 } 00925 00926 /* Wrap up the end of the link buffer */ 00927 wcsncpy(LinkBuffer, DirInfo->Name.Buffer, 2); 00928 LinkBuffer[2] = L'\\'; 00929 LinkBuffer[3] = L'\0'; 00930 00931 /* Now set this as the "BootDir" */ 00932 RtlInitUnicodeString(&UnicodeString, L"BootDir"); 00933 Status = NtSetValueKey(KeyHandle, 00934 &UnicodeString, 00935 0, 00936 REG_SZ, 00937 LinkBuffer, 00938 4 * sizeof(WCHAR)); 00939 if (!NT_SUCCESS(Status)) 00940 { 00941 DPRINT1("SMSS: couldn't write BootDir value: 0x%x\n", Status); 00942 } 00943 NtClose(KeyHandle); 00944 } 00945 00946 NTSTATUS 00947 NTAPI 00948 SmpCreateSecurityDescriptors(IN BOOLEAN InitialCall) 00949 { 00950 NTSTATUS Status; 00951 PSID WorldSid = NULL, AdminSid = NULL, SystemSid = NULL; 00952 PSID RestrictedSid = NULL, OwnerSid = NULL; 00953 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; 00954 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; 00955 SID_IDENTIFIER_AUTHORITY CreatorAuthority = {SECURITY_CREATOR_SID_AUTHORITY}; 00956 ULONG AclLength, SidLength; 00957 PACL Acl; 00958 PACE_HEADER Ace; 00959 BOOLEAN ProtectionRequired = FALSE; 00960 00961 /* Check if this is the first call */ 00962 if (InitialCall) 00963 { 00964 /* Create and set the primary descriptor */ 00965 SmpPrimarySecurityDescriptor = &SmpPrimarySDBody; 00966 Status = RtlCreateSecurityDescriptor(SmpPrimarySecurityDescriptor, 00967 SECURITY_DESCRIPTOR_REVISION); 00968 ASSERT(NT_SUCCESS(Status)); 00969 Status = RtlSetDaclSecurityDescriptor(SmpPrimarySecurityDescriptor, 00970 TRUE, 00971 NULL, 00972 FALSE); 00973 ASSERT(NT_SUCCESS(Status)); 00974 00975 /* Create and set the liberal descriptor */ 00976 SmpLiberalSecurityDescriptor = &SmpLiberalSDBody; 00977 Status = RtlCreateSecurityDescriptor(SmpLiberalSecurityDescriptor, 00978 SECURITY_DESCRIPTOR_REVISION); 00979 ASSERT(NT_SUCCESS(Status)); 00980 Status = RtlSetDaclSecurityDescriptor(SmpLiberalSecurityDescriptor, 00981 TRUE, 00982 NULL, 00983 FALSE); 00984 ASSERT(NT_SUCCESS(Status)); 00985 00986 /* Create and set the \KnownDlls descriptor */ 00987 SmpKnownDllsSecurityDescriptor = &SmpKnownDllsSDBody; 00988 Status = RtlCreateSecurityDescriptor(SmpKnownDllsSecurityDescriptor, 00989 SECURITY_DESCRIPTOR_REVISION); 00990 ASSERT(NT_SUCCESS(Status)); 00991 Status = RtlSetDaclSecurityDescriptor(SmpKnownDllsSecurityDescriptor, 00992 TRUE, 00993 NULL, 00994 FALSE); 00995 ASSERT(NT_SUCCESS(Status)); 00996 00997 /* Create and Set the \ApiPort descriptor */ 00998 SmpApiPortSecurityDescriptor = &SmpApiPortSDBody; 00999 Status = RtlCreateSecurityDescriptor(SmpApiPortSecurityDescriptor, 01000 SECURITY_DESCRIPTOR_REVISION); 01001 ASSERT(NT_SUCCESS(Status)); 01002 Status = RtlSetDaclSecurityDescriptor(SmpApiPortSecurityDescriptor, 01003 TRUE, 01004 NULL, 01005 FALSE); 01006 ASSERT(NT_SUCCESS(Status)); 01007 } 01008 01009 /* Check if protection was requested in the registry (on by default) */ 01010 if (SmpProtectionMode & 1) ProtectionRequired = TRUE; 01011 01012 /* Exit if there's nothing to do */ 01013 if (!(InitialCall || ProtectionRequired)) return STATUS_SUCCESS; 01014 01015 /* Build the world SID */ 01016 Status = RtlAllocateAndInitializeSid(&WorldAuthority, 1, 01017 SECURITY_WORLD_RID, 01018 0, 0, 0, 0, 0, 0, 0, 01019 &WorldSid); 01020 if (!NT_SUCCESS(Status)) 01021 { 01022 WorldSid = NULL; 01023 goto Quickie; 01024 } 01025 01026 /* Build the admin SID */ 01027 Status = RtlAllocateAndInitializeSid(&NtAuthority, 2, 01028 SECURITY_BUILTIN_DOMAIN_RID, 01029 DOMAIN_ALIAS_RID_ADMINS, 01030 0, 0, 0, 0, 0, 0, 01031 &AdminSid); 01032 if (!NT_SUCCESS(Status)) 01033 { 01034 AdminSid = NULL; 01035 goto Quickie; 01036 } 01037 01038 /* Build the owner SID */ 01039 Status = RtlAllocateAndInitializeSid(&CreatorAuthority, 1, 01040 SECURITY_CREATOR_OWNER_RID, 01041 0, 0, 0, 0, 0, 0, 0, 01042 &OwnerSid); 01043 if (!NT_SUCCESS(Status)) 01044 { 01045 OwnerSid = NULL; 01046 goto Quickie; 01047 } 01048 01049 /* Build the restricted SID */ 01050 Status = RtlAllocateAndInitializeSid(&NtAuthority, 1, 01051 SECURITY_RESTRICTED_CODE_RID, 01052 0, 0, 0, 0, 0, 0, 0, 01053 &RestrictedSid); 01054 if (!NT_SUCCESS(Status)) 01055 { 01056 RestrictedSid = NULL; 01057 goto Quickie; 01058 } 01059 01060 /* Build the system SID */ 01061 Status = RtlAllocateAndInitializeSid(&NtAuthority, 1, 01062 SECURITY_LOCAL_SYSTEM_RID, 01063 0, 0, 0, 0, 0, 0, 0, 01064 &SystemSid); 01065 if (!NT_SUCCESS(Status)) 01066 { 01067 SystemSid = NULL; 01068 goto Quickie; 01069 } 01070 01071 /* Now check if we're creating the core descriptors */ 01072 if (!InitialCall) 01073 { 01074 /* We're skipping NextAcl so we have to do this here */ 01075 SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(RestrictedSid) + RtlLengthSid(AdminSid); 01076 SidLength *= 2; 01077 goto NotInitial; 01078 } 01079 01080 /* Allocate an ACL with two ACEs with two SIDs each */ 01081 SidLength = RtlLengthSid(SystemSid) + RtlLengthSid(AdminSid); 01082 AclLength = sizeof(ACL) + 2 * sizeof(ACCESS_ALLOWED_ACE) + SidLength; 01083 Acl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclLength); 01084 if (!Acl) Status = STATUS_NO_MEMORY; 01085 if (!NT_SUCCESS(Status)) goto NextAcl; 01086 01087 /* Now build the ACL and add the two ACEs */ 01088 Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION2); 01089 ASSERT(NT_SUCCESS(Status)); 01090 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid); 01091 ASSERT(NT_SUCCESS(Status)); 01092 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, SystemSid); 01093 ASSERT(NT_SUCCESS(Status)); 01094 01095 /* Set this as the DACL */ 01096 Status = RtlSetDaclSecurityDescriptor(SmpApiPortSecurityDescriptor, 01097 TRUE, 01098 Acl, 01099 FALSE); 01100 ASSERT(NT_SUCCESS(Status)); 01101 01102 NextAcl: 01103 /* Allocate an ACL with 6 ACEs, two ACEs per SID */ 01104 SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(RestrictedSid) + RtlLengthSid(AdminSid); 01105 SidLength *= 2; 01106 AclLength = sizeof(ACL) + 6 * sizeof(ACCESS_ALLOWED_ACE) + SidLength; 01107 Acl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclLength); 01108 if (!Acl) Status = STATUS_NO_MEMORY; 01109 if (!NT_SUCCESS(Status)) goto NotInitial; 01110 01111 /* Now build the ACL and add the six ACEs */ 01112 Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION2); 01113 ASSERT(NT_SUCCESS(Status)); 01114 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE, WorldSid); 01115 ASSERT(NT_SUCCESS(Status)); 01116 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE, RestrictedSid); 01117 ASSERT(NT_SUCCESS(Status)); 01118 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid); 01119 ASSERT(NT_SUCCESS(Status)); 01120 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE, WorldSid); 01121 ASSERT(NT_SUCCESS(Status)); 01122 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE, RestrictedSid); 01123 ASSERT(NT_SUCCESS(Status)); 01124 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid); 01125 ASSERT(NT_SUCCESS(Status)); 01126 01127 /* Now edit the last three ACEs and make them inheritable */ 01128 Status = RtlGetAce(Acl, 3, (PVOID)&Ace); 01129 ASSERT(NT_SUCCESS(Status)); 01130 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01131 Status = RtlGetAce(Acl, 4, (PVOID)&Ace); 01132 ASSERT(NT_SUCCESS(Status)); 01133 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01134 Status = RtlGetAce(Acl, 5, (PVOID)&Ace); 01135 ASSERT(NT_SUCCESS(Status)); 01136 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01137 01138 /* Set this as the DACL */ 01139 Status = RtlSetDaclSecurityDescriptor(SmpKnownDllsSecurityDescriptor, 01140 TRUE, 01141 Acl, 01142 FALSE); 01143 ASSERT(NT_SUCCESS(Status)); 01144 01145 NotInitial: 01146 /* The initial ACLs have been created, are we also protecting objects? */ 01147 if (!ProtectionRequired) goto Quickie; 01148 01149 /* Allocate an ACL with 7 ACEs, two ACEs per SID, and one final owner ACE */ 01150 SidLength += RtlLengthSid(OwnerSid); 01151 AclLength = sizeof(ACL) + 7 * sizeof (ACCESS_ALLOWED_ACE) + 2 * SidLength; 01152 Acl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclLength); 01153 if (!Acl) Status = STATUS_NO_MEMORY; 01154 if (!NT_SUCCESS(Status)) goto Quickie; 01155 01156 /* Build the ACL and add the seven ACEs */ 01157 Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION2); 01158 ASSERT(NT_SUCCESS(Status)); 01159 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ, WorldSid); 01160 ASSERT(NT_SUCCESS(Status)); 01161 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ, RestrictedSid); 01162 ASSERT(NT_SUCCESS(Status)); 01163 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid); 01164 ASSERT(NT_SUCCESS(Status)); 01165 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ, WorldSid); 01166 ASSERT(NT_SUCCESS(Status)); 01167 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ, RestrictedSid); 01168 ASSERT(NT_SUCCESS(Status)); 01169 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid); 01170 ASSERT(NT_SUCCESS(Status)); 01171 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, OwnerSid); 01172 ASSERT(NT_SUCCESS(Status)); 01173 01174 /* Edit the last 4 ACEs to make then inheritable */ 01175 Status = RtlGetAce(Acl, 3, (PVOID)&Ace); 01176 ASSERT(NT_SUCCESS(Status)); 01177 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01178 Status = RtlGetAce(Acl, 4, (PVOID)&Ace); 01179 ASSERT(NT_SUCCESS(Status)); 01180 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01181 Status = RtlGetAce(Acl, 5, (PVOID)&Ace); 01182 ASSERT(NT_SUCCESS(Status)); 01183 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01184 Status = RtlGetAce(Acl, 6, (PVOID)&Ace); 01185 ASSERT(NT_SUCCESS(Status)); 01186 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01187 01188 /* Set this as the DACL for the primary SD */ 01189 Status = RtlSetDaclSecurityDescriptor(SmpPrimarySecurityDescriptor, 01190 TRUE, 01191 Acl, 01192 FALSE); 01193 ASSERT(NT_SUCCESS(Status)); 01194 01195 /* Allocate an ACL with 7 ACEs, two ACEs per SID, and one final owner ACE */ 01196 AclLength = sizeof(ACL) + 7 * sizeof (ACCESS_ALLOWED_ACE) + 2 * SidLength; 01197 Acl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclLength); 01198 if (!Acl) Status = STATUS_NO_MEMORY; 01199 if (!NT_SUCCESS(Status)) goto Quickie; 01200 01201 /* Build the ACL and add the seven ACEs */ 01202 Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION2); 01203 ASSERT(NT_SUCCESS(Status)); 01204 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE, WorldSid); 01205 ASSERT(NT_SUCCESS(Status)); 01206 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE, RestrictedSid); 01207 ASSERT(NT_SUCCESS(Status)); 01208 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid); 01209 ASSERT(NT_SUCCESS(Status)); 01210 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE, WorldSid); 01211 ASSERT(NT_SUCCESS(Status)); 01212 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE, RestrictedSid); 01213 ASSERT(NT_SUCCESS(Status)); 01214 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid); 01215 ASSERT(NT_SUCCESS(Status)); 01216 Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, OwnerSid); 01217 ASSERT(NT_SUCCESS(Status)); 01218 01219 /* Edit the last 4 ACEs to make then inheritable */ 01220 Status = RtlGetAce(Acl, 3, (PVOID)&Ace); 01221 ASSERT(NT_SUCCESS(Status)); 01222 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01223 Status = RtlGetAce(Acl, 4, (PVOID)&Ace); 01224 ASSERT(NT_SUCCESS(Status)); 01225 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01226 Status = RtlGetAce(Acl, 5, (PVOID)&Ace); 01227 ASSERT(NT_SUCCESS(Status)); 01228 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01229 Status = RtlGetAce(Acl, 6, (PVOID)&Ace); 01230 ASSERT(NT_SUCCESS(Status)); 01231 Ace->AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; 01232 01233 /* Now set this as the DACL for the liberal SD */ 01234 Status = RtlSetDaclSecurityDescriptor(SmpLiberalSecurityDescriptor, 01235 TRUE, 01236 Acl, 01237 FALSE); 01238 ASSERT(NT_SUCCESS(Status)); 01239 01240 Quickie: 01241 /* Cleanup the SIDs */ 01242 if (OwnerSid) RtlFreeHeap(RtlGetProcessHeap(), 0, OwnerSid); 01243 if (AdminSid) RtlFreeHeap(RtlGetProcessHeap(), 0, AdminSid); 01244 if (WorldSid) RtlFreeHeap(RtlGetProcessHeap(), 0, WorldSid); 01245 if (SystemSid) RtlFreeHeap(RtlGetProcessHeap(), 0, SystemSid); 01246 if (RestrictedSid) RtlFreeHeap(RtlGetProcessHeap(), 0, RestrictedSid); 01247 return Status; 01248 } 01249 01250 NTSTATUS 01251 NTAPI 01252 SmpInitializeDosDevices(VOID) 01253 { 01254 NTSTATUS Status; 01255 PSMP_REGISTRY_VALUE RegEntry; 01256 SECURITY_DESCRIPTOR_CONTROL OldFlag = 0; 01257 OBJECT_ATTRIBUTES ObjectAttributes; 01258 UNICODE_STRING DestinationString; 01259 HANDLE DirHandle; 01260 PLIST_ENTRY NextEntry, Head; 01261 01262 /* Open the GLOBAL?? directory */ 01263 RtlInitUnicodeString(&DestinationString, L"\\??"); 01264 InitializeObjectAttributes(&ObjectAttributes, 01265 &DestinationString, 01266 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT, 01267 NULL, 01268 NULL); 01269 Status = NtOpenDirectoryObject(&SmpDosDevicesObjectDirectory, 01270 DIRECTORY_ALL_ACCESS, 01271 &ObjectAttributes); 01272 if (!NT_SUCCESS(Status)) 01273 { 01274 DPRINT1("SMSS: Unable to open %wZ directory - Status == %lx\n", 01275 &DestinationString, Status); 01276 return Status; 01277 } 01278 01279 /* Loop the DOS devices */ 01280 Head = &SmpDosDevicesList; 01281 while (!IsListEmpty(Head)) 01282 { 01283 /* Get the entry and remove it */ 01284 NextEntry = RemoveHeadList(Head); 01285 RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry); 01286 01287 /* Initialize the attributes, and see which descriptor is being used */ 01288 InitializeObjectAttributes(&ObjectAttributes, 01289 &RegEntry->Name, 01290 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT, 01291 SmpDosDevicesObjectDirectory, 01292 SmpPrimarySecurityDescriptor); 01293 if (SmpPrimarySecurityDescriptor) 01294 { 01295 /* Save the old flag and set it while we create this link */ 01296 OldFlag = SmpPrimarySecurityDescriptor->Control; 01297 SmpPrimarySecurityDescriptor->Control |= SE_DACL_DEFAULTED; 01298 } 01299 01300 /* Create the symbolic link */ 01301 DPRINT("Creating symlink for %wZ to %wZ\n", &RegEntry->Name, &RegEntry->Value); 01302 Status = NtCreateSymbolicLinkObject(&DirHandle, 01303 SYMBOLIC_LINK_ALL_ACCESS, 01304 &ObjectAttributes, 01305 &RegEntry->Value); 01306 if (Status == STATUS_OBJECT_NAME_EXISTS) 01307 { 01308 /* Make it temporary and get rid of the handle */ 01309 NtMakeTemporaryObject(DirHandle); 01310 NtClose(DirHandle); 01311 01312 /* Treat this as success, and see if we got a name back */ 01313 Status = STATUS_SUCCESS; 01314 if (RegEntry->Value.Length) 01315 { 01316 /* Create it now with this name */ 01317 ObjectAttributes.Attributes &= ~OBJ_OPENIF; 01318 Status = NtCreateSymbolicLinkObject(&DirHandle, 01319 SYMBOLIC_LINK_ALL_ACCESS, 01320 &ObjectAttributes, 01321 &RegEntry->Value); 01322 } 01323 } 01324 01325 /* If we were using a security descriptor, restore the non-defaulted flag */ 01326 if (ObjectAttributes.SecurityDescriptor) 01327 { 01328 SmpPrimarySecurityDescriptor->Control = OldFlag; 01329 } 01330 01331 /* Print a failure if we failed to create the symbolic link */ 01332 if (!NT_SUCCESS(Status)) 01333 { 01334 DPRINT1("SMSS: Unable to create %wZ => %wZ symbolic link object - Status == 0x%lx\n", 01335 &RegEntry->Name, 01336 &RegEntry->Value, 01337 Status); 01338 break; 01339 } 01340 01341 /* Close the handle */ 01342 NtClose(DirHandle); 01343 01344 /* Free this entry */ 01345 if (RegEntry->AnsiValue) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue); 01346 if (RegEntry->Value.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer); 01347 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry); 01348 } 01349 01350 /* Return the status */ 01351 return Status; 01352 } 01353 01354 VOID 01355 NTAPI 01356 SmpProcessModuleImports(IN PVOID Unused, 01357 IN PCHAR ImportName) 01358 { 01359 ULONG Length = 0, Chars; 01360 WCHAR Buffer[MAX_PATH]; 01361 PWCHAR DllName, DllValue; 01362 ANSI_STRING ImportString; 01363 UNICODE_STRING ImportUnicodeString; 01364 NTSTATUS Status; 01365 01366 /* Skip NTDLL since it's already always mapped */ 01367 if (!_stricmp(ImportName, "ntdll.dll")) return; 01368 01369 /* Initialize our strings */ 01370 RtlInitAnsiString(&ImportString, ImportName); 01371 RtlInitEmptyUnicodeString(&ImportUnicodeString, Buffer, sizeof(Buffer)); 01372 Status = RtlAnsiStringToUnicodeString(&ImportUnicodeString, &ImportString, FALSE); 01373 if (!NT_SUCCESS(Status)) return; 01374 01375 /* Loop in case we find a forwarder */ 01376 ImportUnicodeString.MaximumLength = ImportUnicodeString.Length + sizeof(UNICODE_NULL); 01377 while (Length < ImportUnicodeString.Length) 01378 { 01379 if (ImportUnicodeString.Buffer[Length / sizeof(WCHAR)] == L'.') break; 01380 Length += sizeof(WCHAR); 01381 } 01382 01383 /* Break up the values as needed */ 01384 DllValue = ImportUnicodeString.Buffer; 01385 DllName = &ImportUnicodeString.Buffer[ImportUnicodeString.MaximumLength / sizeof(WCHAR)]; 01386 Chars = Length >> 1; 01387 wcsncpy(DllName, ImportUnicodeString.Buffer, Chars); 01388 DllName[Chars] = 0; 01389 01390 /* Add the DLL to the list */ 01391 SmpSaveRegistryValue(&SmpKnownDllsList, DllName, DllValue, TRUE); 01392 } 01393 01394 NTSTATUS 01395 NTAPI 01396 SmpInitializeKnownDllsInternal(IN PUNICODE_STRING Directory, 01397 IN PUNICODE_STRING Path) 01398 { 01399 HANDLE DirFileHandle, DirHandle, SectionHandle, FileHandle, LinkHandle; 01400 UNICODE_STRING NtPath, DestinationString; 01401 OBJECT_ATTRIBUTES ObjectAttributes; 01402 NTSTATUS Status, Status1; 01403 PLIST_ENTRY NextEntry; 01404 PSMP_REGISTRY_VALUE RegEntry; 01405 ULONG_PTR ErrorParameters[3]; 01406 UNICODE_STRING ErrorResponse; 01407 IO_STATUS_BLOCK IoStatusBlock; 01408 SECURITY_DESCRIPTOR_CONTROL OldFlag = 0; 01409 USHORT ImageCharacteristics; 01410 01411 /* Initialize to NULL */ 01412 DirFileHandle = NULL; 01413 DirHandle = NULL; 01414 NtPath.Buffer = NULL; 01415 01416 /* Create the \KnownDLLs directory */ 01417 InitializeObjectAttributes(&ObjectAttributes, 01418 Directory, 01419 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT, 01420 NULL, 01421 SmpKnownDllsSecurityDescriptor); 01422 Status = NtCreateDirectoryObject(&DirHandle, 01423 DIRECTORY_ALL_ACCESS, 01424 &ObjectAttributes); 01425 if (!NT_SUCCESS(Status)) 01426 { 01427 /* Handle failure */ 01428 DPRINT1("SMSS: Unable to create %wZ directory - Status == %lx\n", 01429 Directory, Status); 01430 return Status; 01431 } 01432 01433 /* Convert the path to native format */ 01434 if (!RtlDosPathNameToNtPathName_U(Path->Buffer, &NtPath, NULL, NULL)) 01435 { 01436 /* Fail if this didn't work */ 01437 DPRINT1("SMSS: Unable to to convert %wZ to an Nt path\n", Path); 01438 Status = STATUS_OBJECT_NAME_INVALID; 01439 goto Quickie; 01440 } 01441 01442 /* Open the path that was specified, which should be a directory */ 01443 InitializeObjectAttributes(&ObjectAttributes, 01444 &NtPath, 01445 OBJ_CASE_INSENSITIVE, 01446 NULL, 01447 NULL); 01448 Status = NtOpenFile(&DirFileHandle, 01449 FILE_LIST_DIRECTORY | SYNCHRONIZE, 01450 &ObjectAttributes, 01451 &IoStatusBlock, 01452 FILE_SHARE_READ | FILE_SHARE_WRITE, 01453 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); 01454 if (!NT_SUCCESS(Status)) 01455 { 01456 /* Fail if we couldn't open it */ 01457 DPRINT1("SMSS: Unable to open a handle to the KnownDll directory (%wZ)" 01458 "- Status == %lx\n", 01459 Path, 01460 Status); 01461 FileHandle = NULL; 01462 goto Quickie; 01463 } 01464 01465 /* Temporarily hack the SD to use a default DACL for this symbolic link */ 01466 if (SmpPrimarySecurityDescriptor) 01467 { 01468 OldFlag = SmpPrimarySecurityDescriptor->Control; 01469 SmpPrimarySecurityDescriptor->Control |= SE_DACL_DEFAULTED; 01470 } 01471 01472 /* Create a symbolic link to the directory in the object manager */ 01473 RtlInitUnicodeString(&DestinationString, L"KnownDllPath"); 01474 InitializeObjectAttributes(&ObjectAttributes, 01475 &DestinationString, 01476 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT, 01477 DirHandle, 01478 SmpPrimarySecurityDescriptor); 01479 Status = NtCreateSymbolicLinkObject(&LinkHandle, 01480 SYMBOLIC_LINK_ALL_ACCESS, 01481 &ObjectAttributes, 01482 Path); 01483 01484 /* Undo the hack */ 01485 if (SmpPrimarySecurityDescriptor) SmpPrimarySecurityDescriptor->Control = OldFlag; 01486 01487 /* Check if the symlink was created */ 01488 if (!NT_SUCCESS(Status)) 01489 { 01490 /* It wasn't, so bail out since the OS needs it to exist */ 01491 DPRINT1("SMSS: Unable to create %wZ symbolic link - Status == %lx\n", 01492 &DestinationString, Status); 01493 LinkHandle = NULL; 01494 goto Quickie; 01495 } 01496 01497 /* We created it permanent, we can go ahead and close the handle now */ 01498 Status1 = NtClose(LinkHandle); 01499 ASSERT(NT_SUCCESS(Status1)); 01500 01501 /* Now loop the known DLLs */ 01502 NextEntry = SmpKnownDllsList.Flink; 01503 while (NextEntry != &SmpKnownDllsList) 01504 { 01505 /* Get the entry and skip it if it's in the exluded list */ 01506 RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry); 01507 DPRINT("Processing known DLL: %wZ-%wZ\n", &RegEntry->Name, &RegEntry->Value); 01508 if ((SmpFindRegistryValue(&SmpExcludeKnownDllsList, 01509 RegEntry->Name.Buffer)) || 01510 (SmpFindRegistryValue(&SmpExcludeKnownDllsList, 01511 RegEntry->Value.Buffer))) 01512 { 01513 continue; 01514 } 01515 01516 /* Open the actual file */ 01517 InitializeObjectAttributes(&ObjectAttributes, 01518 &RegEntry->Value, 01519 OBJ_CASE_INSENSITIVE, 01520 DirFileHandle, 01521 NULL); 01522 Status = NtOpenFile(&FileHandle, 01523 SYNCHRONIZE | FILE_EXECUTE, 01524 &ObjectAttributes, 01525 &IoStatusBlock, 01526 FILE_SHARE_READ | FILE_SHARE_DELETE, 01527 FILE_NON_DIRECTORY_FILE | 01528 FILE_SYNCHRONOUS_IO_NONALERT); 01529 if (!NT_SUCCESS(Status)) break; 01530 01531 /* Checksum it */ 01532 Status = LdrVerifyImageMatchesChecksum((HANDLE)((ULONG_PTR)FileHandle | 1), 01533 SmpProcessModuleImports, 01534 RegEntry, 01535 &ImageCharacteristics); 01536 #if 0 01537 if (!NT_SUCCESS(Status)) 01538 { 01539 /* Checksum failed, so don't even try going further -- kill SMSS */ 01540 RtlInitUnicodeString(&ErrorResponse, 01541 L"Verification of a KnownDLL failed."); 01542 ErrorParameters[0] = (ULONG)&ErrorResponse; 01543 ErrorParameters[1] = Status; 01544 ErrorParameters[2] = (ULONG)&RegEntry->Value; 01545 SmpTerminate(ErrorParameters, 5, RTL_NUMBER_OF(ErrorParameters)); 01546 } 01547 else 01548 #endif 01549 if (!(ImageCharacteristics & IMAGE_FILE_DLL)) 01550 { 01551 /* An invalid known DLL entry will also kill SMSS */ 01552 RtlInitUnicodeString(&ErrorResponse, 01553 L"Non-DLL file included in KnownDLL list."); 01554 ErrorParameters[0] = (ULONG)&ErrorResponse; 01555 ErrorParameters[1] = STATUS_INVALID_IMPORT_OF_NON_DLL; 01556 ErrorParameters[2] = (ULONG)&RegEntry->Value; 01557 SmpTerminate(ErrorParameters, 5, RTL_NUMBER_OF(ErrorParameters)); 01558 } 01559 01560 /* Temporarily hack the SD to use a default DACL for this section */ 01561 if (SmpLiberalSecurityDescriptor) 01562 { 01563 OldFlag = SmpLiberalSecurityDescriptor->Control; 01564 SmpLiberalSecurityDescriptor->Control |= SE_DACL_DEFAULTED; 01565 } 01566 01567 /* Create the section for this known DLL */ 01568 InitializeObjectAttributes(&ObjectAttributes, 01569 &RegEntry->Value, 01570 OBJ_PERMANENT, 01571 DirHandle, 01572 SmpLiberalSecurityDescriptor) 01573 Status = NtCreateSection(&SectionHandle, 01574 SECTION_ALL_ACCESS, 01575 &ObjectAttributes, 01576 0, 01577 PAGE_EXECUTE, 01578 SEC_IMAGE, 01579 FileHandle); 01580 01581 /* Undo the hack */ 01582 if (SmpLiberalSecurityDescriptor) SmpLiberalSecurityDescriptor->Control = OldFlag; 01583 01584 /* Check if we created the section okay */ 01585 if (NT_SUCCESS(Status)) 01586 { 01587 /* We can close it now, since it's marked permanent */ 01588 Status1 = NtClose(SectionHandle); 01589 ASSERT(NT_SUCCESS(Status1)); 01590 } 01591 else 01592 { 01593 /* If we couldn't make it "known", that's fine and keep going */ 01594 DPRINT1("SMSS: CreateSection for KnownDll %wZ failed - Status == %lx\n", 01595 &RegEntry->Value, Status); 01596 } 01597 01598 /* Close the file since we can move on to the next one */ 01599 Status1 = NtClose(FileHandle); 01600 ASSERT(NT_SUCCESS(Status1)); 01601 01602 /* Go to the next entry */ 01603 NextEntry = NextEntry->Flink; 01604 } 01605 01606 Quickie: 01607 /* Close both handles and free the NT path buffer */ 01608 if (DirHandle) 01609 { 01610 Status1 = NtClose(DirHandle); 01611 ASSERT(NT_SUCCESS(Status1)); 01612 } 01613 if (DirFileHandle) 01614 { 01615 Status1 = NtClose(DirFileHandle); 01616 ASSERT(NT_SUCCESS(Status1)); 01617 } 01618 if (NtPath.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, NtPath.Buffer); 01619 return Status; 01620 } 01621 01622 NTSTATUS 01623 NTAPI 01624 SmpInitializeKnownDlls(VOID) 01625 { 01626 NTSTATUS Status; 01627 PSMP_REGISTRY_VALUE RegEntry; 01628 UNICODE_STRING DestinationString; 01629 PLIST_ENTRY Head, NextEntry; 01630 01631 /* Call the internal function */ 01632 RtlInitUnicodeString(&DestinationString, L"\\KnownDlls"); 01633 Status = SmpInitializeKnownDllsInternal(&DestinationString, &SmpKnownDllPath); 01634 01635 /* Wipe out the list regardless of success */ 01636 Head = &SmpKnownDllsList; 01637 while (!IsListEmpty(Head)) 01638 { 01639 /* Remove this entry */ 01640 NextEntry = RemoveHeadList(Head); 01641 01642 /* Free it */ 01643 RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry); 01644 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue); 01645 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer); 01646 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry); 01647 } 01648 01649 /* All done */ 01650 return Status; 01651 } 01652 01653 NTSTATUS 01654 NTAPI 01655 SmpCreateDynamicEnvironmentVariables(VOID) 01656 { 01657 NTSTATUS Status; 01658 SYSTEM_BASIC_INFORMATION BasicInfo; 01659 SYSTEM_PROCESSOR_INFORMATION ProcessorInfo; 01660 OBJECT_ATTRIBUTES ObjectAttributes; 01661 UNICODE_STRING ValueName, DestinationString; 01662 HANDLE KeyHandle, KeyHandle2; 01663 ULONG ResultLength; 01664 PWCHAR ArchName; 01665 WCHAR ValueBuffer[512], ValueBuffer2[512]; 01666 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)ValueBuffer; 01667 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo2 = (PVOID)ValueBuffer2; 01668 01669 /* Get system basic information -- we'll need the CPU count */ 01670 Status = NtQuerySystemInformation(SystemBasicInformation, 01671 &BasicInfo, 01672 sizeof(BasicInfo), 01673 NULL); 01674 if (!NT_SUCCESS(Status)) 01675 { 01676 /* Bail out on failure */ 01677 DPRINT1("SMSS: Unable to query system basic information - %x\n", Status); 01678 return Status; 01679 } 01680 01681 /* Get the processor information, we'll query a bunch of revision info */ 01682 Status = NtQuerySystemInformation(SystemProcessorInformation, 01683 &ProcessorInfo, 01684 sizeof(ProcessorInfo), 01685 NULL); 01686 if (!NT_SUCCESS(Status)) 01687 { 01688 /* Bail out on failure */ 01689 DPRINT1("SMSS: Unable to query system processor information - %x\n", Status); 01690 return Status; 01691 } 01692 01693 /* We'll be writing all these environment variables over here */ 01694 RtlInitUnicodeString(&DestinationString, 01695 L"\\Registry\\Machine\\System\\CurrentControlSet\\" 01696 L"Control\\Session Manager\\Environment"); 01697 InitializeObjectAttributes(&ObjectAttributes, 01698 &DestinationString, 01699 OBJ_CASE_INSENSITIVE, 01700 NULL, 01701 NULL); 01702 Status = NtOpenKey(&KeyHandle, GENERIC_WRITE, &ObjectAttributes); 01703 if (!NT_SUCCESS(Status)) 01704 { 01705 /* Bail out on failure */ 01706 DPRINT1("SMSS: Unable to open %wZ - %x\n", &DestinationString, Status); 01707 return Status; 01708 } 01709 01710 /* First let's write the OS variable */ 01711 RtlInitUnicodeString(&ValueName, L"OS"); 01712 DPRINT("Setting %wZ to %S\n", &ValueName, L"Windows_NT"); 01713 Status = NtSetValueKey(KeyHandle, 01714 &ValueName, 01715 0, 01716 REG_SZ, 01717 L"Windows_NT", 01718 wcslen(L"Windows_NT") * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 01719 if (!NT_SUCCESS(Status)) 01720 { 01721 DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n", 01722 &ValueName, Status); 01723 NtClose(KeyHandle); 01724 return Status; 01725 } 01726 01727 /* Next, let's write the CPU architecture variable */ 01728 RtlInitUnicodeString(&ValueName, L"PROCESSOR_ARCHITECTURE"); 01729 switch (ProcessorInfo.ProcessorArchitecture) 01730 { 01731 /* Pick the correct string that matches the architecture */ 01732 case PROCESSOR_ARCHITECTURE_INTEL: 01733 ArchName = L"x86"; 01734 break; 01735 01736 case PROCESSOR_ARCHITECTURE_AMD64: 01737 ArchName = L"AMD64"; 01738 break; 01739 01740 case PROCESSOR_ARCHITECTURE_IA64: 01741 ArchName = L"IA64"; 01742 break; 01743 01744 default: 01745 ArchName = L"Unknown"; 01746 break; 01747 } 01748 01749 /* Set it */ 01750 DPRINT("Setting %wZ to %S\n", &ValueName, ArchName); 01751 Status = NtSetValueKey(KeyHandle, 01752 &ValueName, 01753 0, 01754 REG_SZ, 01755 ArchName, 01756 wcslen(ArchName) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 01757 if (!NT_SUCCESS(Status)) 01758 { 01759 DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n", 01760 &ValueName, Status); 01761 NtClose(KeyHandle); 01762 return Status; 01763 } 01764 01765 /* And now let's write the processor level */ 01766 RtlInitUnicodeString(&ValueName, L"PROCESSOR_LEVEL"); 01767 swprintf(ValueBuffer, L"%u", ProcessorInfo.ProcessorLevel); 01768 DPRINT("Setting %wZ to %S\n", &ValueName, ValueBuffer); 01769 Status = NtSetValueKey(KeyHandle, 01770 &ValueName, 01771 0, 01772 REG_SZ, 01773 ValueBuffer, 01774 wcslen(ValueBuffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 01775 if (!NT_SUCCESS(Status)) 01776 { 01777 DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n", 01778 &ValueName, Status); 01779 NtClose(KeyHandle); 01780 return Status; 01781 } 01782 01783 /* Now open the hardware CPU key */ 01784 RtlInitUnicodeString(&DestinationString, 01785 L"\\Registry\\Machine\\Hardware\\Description\\System\\" 01786 L"CentralProcessor\\0"); 01787 InitializeObjectAttributes(&ObjectAttributes, 01788 &DestinationString, 01789 OBJ_CASE_INSENSITIVE, 01790 NULL, 01791 NULL); 01792 Status = NtOpenKey(&KeyHandle2, KEY_READ, &ObjectAttributes); 01793 if (!NT_SUCCESS(Status)) 01794 { 01795 DPRINT1("SMSS: Unable to open %wZ - %x\n", &DestinationString, Status); 01796 NtClose(KeyHandle); 01797 return Status; 01798 } 01799 01800 /* So that we can read the identifier out of it... */ 01801 RtlInitUnicodeString(&ValueName, L"Identifier"); 01802 Status = NtQueryValueKey(KeyHandle2, 01803 &ValueName, 01804 KeyValuePartialInformation, 01805 PartialInfo, 01806 sizeof(ValueBuffer), 01807 &ResultLength); 01808 if (!NT_SUCCESS(Status)) 01809 { 01810 NtClose(KeyHandle2); 01811 NtClose(KeyHandle); 01812 DPRINT1("SMSS: Unable to read %wZ\\%wZ - %x\n", 01813 &DestinationString, &ValueName, Status); 01814 return Status; 01815 } 01816 01817 /* As well as the vendor... */ 01818 RtlInitUnicodeString(&ValueName, L"VendorIdentifier"); 01819 Status = NtQueryValueKey(KeyHandle2, 01820 &ValueName, 01821 KeyValuePartialInformation, 01822 PartialInfo2, 01823 sizeof(ValueBuffer2), 01824 &ResultLength); 01825 NtClose(KeyHandle2); 01826 if (NT_SUCCESS(Status)) 01827 { 01828 /* To combine it into a single string */ 01829 swprintf((PWCHAR)PartialInfo->Data + wcslen((PWCHAR)PartialInfo->Data), 01830 L", %ws", 01831 PartialInfo2->Data); 01832 } 01833 01834 /* So that we can set this as the PROCESSOR_IDENTIFIER variable */ 01835 RtlInitUnicodeString(&ValueName, L"PROCESSOR_IDENTIFIER"); 01836 DPRINT("Setting %wZ to %S\n", &ValueName, PartialInfo->Data); 01837 Status = NtSetValueKey(KeyHandle, 01838 &ValueName, 01839 0, 01840 REG_SZ, 01841 PartialInfo->Data, 01842 wcslen((PWCHAR)PartialInfo->Data) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 01843 if (!NT_SUCCESS(Status)) 01844 { 01845 DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n", 01846 &ValueName, Status); 01847 NtClose(KeyHandle); 01848 return Status; 01849 } 01850 01851 /* Now let's get the processor architecture */ 01852 RtlInitUnicodeString(&ValueName, L"PROCESSOR_REVISION"); 01853 switch (ProcessorInfo.ProcessorArchitecture) 01854 { 01855 /* Check if this is an older Intel CPU */ 01856 case PROCESSOR_ARCHITECTURE_INTEL: 01857 if ((ProcessorInfo.ProcessorRevision >> 8) == 0xFF) 01858 { 01859 /* These guys used a revision + stepping, so get the rev only */ 01860 swprintf(ValueBuffer, L"%02x", ProcessorInfo.ProcessorRevision & 0xFF); 01861 _wcsupr(ValueBuffer); 01862 break; 01863 } 01864 01865 /* Modern Intel, as well as 64-bit CPUs use a revision without stepping */ 01866 case PROCESSOR_ARCHITECTURE_IA64: 01867 case PROCESSOR_ARCHITECTURE_AMD64: 01868 swprintf(ValueBuffer, L"%04x", ProcessorInfo.ProcessorRevision); 01869 break; 01870 01871 /* And anything else we'll just read the whole revision identifier */ 01872 default: 01873 swprintf(ValueBuffer, L"%u", ProcessorInfo.ProcessorRevision); 01874 break; 01875 } 01876 01877 /* Write the revision to the registry */ 01878 DPRINT("Setting %wZ to %S\n", &ValueName, ValueBuffer); 01879 Status = NtSetValueKey(KeyHandle, 01880 &ValueName, 01881 0, 01882 REG_SZ, 01883 ValueBuffer, 01884 wcslen(ValueBuffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 01885 if (!NT_SUCCESS(Status)) 01886 { 01887 DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n", 01888 &ValueName, Status); 01889 NtClose(KeyHandle); 01890 return Status; 01891 } 01892 01893 /* And finally, write the number of CPUs */ 01894 RtlInitUnicodeString(&ValueName, L"NUMBER_OF_PROCESSORS"); 01895 swprintf(ValueBuffer, L"%u", BasicInfo.NumberOfProcessors); 01896 DPRINT("Setting %wZ to %S\n", &ValueName, ValueBuffer); 01897 Status = NtSetValueKey(KeyHandle, 01898 &ValueName, 01899 0, 01900 REG_SZ, 01901 ValueBuffer, 01902 wcslen(ValueBuffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 01903 if (!NT_SUCCESS(Status)) 01904 { 01905 DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n", 01906 &ValueName, Status); 01907 NtClose(KeyHandle); 01908 return Status; 01909 } 01910 01911 /* Now we need to write the safeboot option key in a different format */ 01912 RtlInitUnicodeString(&DestinationString, 01913 L"\\Registry\\Machine\\System\\CurrentControlSet\\" 01914 L"Control\\Safeboot\\Option"); 01915 InitializeObjectAttributes(&ObjectAttributes, 01916 &DestinationString, 01917 OBJ_CASE_INSENSITIVE, 01918 NULL, 01919 NULL); 01920 Status = NtOpenKey(&KeyHandle2, KEY_ALL_ACCESS, &ObjectAttributes); 01921 if (NT_SUCCESS(Status)) 01922 { 01923 /* This was indeed a safeboot, so check what kind of safeboot it was */ 01924 RtlInitUnicodeString(&ValueName, L"OptionValue"); 01925 Status = NtQueryValueKey(KeyHandle2, 01926 &ValueName, 01927 KeyValuePartialInformation, 01928 PartialInfo, 01929 sizeof(ValueBuffer), 01930 &ResultLength); 01931 NtClose(KeyHandle2); 01932 if (NT_SUCCESS(Status)) 01933 { 01934 /* Convert from the integer value to the correct specifier */ 01935 RtlInitUnicodeString(&ValueName, L"SAFEBOOT_OPTION"); 01936 switch (*(PULONG)PartialInfo->Data) 01937 { 01938 case 1: 01939 wcscpy(ValueBuffer, L"MINIMAL"); 01940 break; 01941 case 2: 01942 wcscpy(ValueBuffer, L"NETWORK"); 01943 break; 01944 case 3: 01945 wcscpy(ValueBuffer, L"DSREPAIR"); 01946 break; 01947 } 01948 01949 /* And write it in the environment! */ 01950 DPRINT("Setting %wZ to %S\n", &ValueName, ValueBuffer); 01951 Status = NtSetValueKey(KeyHandle, 01952 &ValueName, 01953 0, 01954 REG_SZ, 01955 ValueBuffer, 01956 wcslen(ValueBuffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); 01957 if (!NT_SUCCESS(Status)) 01958 { 01959 DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n", 01960 &ValueName, Status); 01961 NtClose(KeyHandle); 01962 return Status; 01963 } 01964 } 01965 else 01966 { 01967 DPRINT1("SMSS: Failed querying safeboot option = %x\n", Status); 01968 } 01969 } 01970 01971 /* We are all done now */ 01972 NtClose(KeyHandle); 01973 return STATUS_SUCCESS; 01974 } 01975 01976 NTSTATUS 01977 NTAPI 01978 SmpProcessFileRenames(VOID) 01979 { 01980 BOOLEAN OldState, HavePrivilege = FALSE; 01981 NTSTATUS Status; 01982 HANDLE FileHandle, OtherFileHandle; 01983 FILE_INFORMATION_CLASS InformationClass; 01984 OBJECT_ATTRIBUTES ObjectAttributes; 01985 IO_STATUS_BLOCK IoStatusBlock; 01986 UNICODE_STRING FileString; 01987 FILE_BASIC_INFORMATION BasicInfo; 01988 FILE_DISPOSITION_INFORMATION DeleteInformation; 01989 PFILE_RENAME_INFORMATION Buffer; 01990 PLIST_ENTRY Head, NextEntry; 01991 PSMP_REGISTRY_VALUE RegEntry; 01992 PWCHAR FileName; 01993 ULONG ValueLength, Length; 01994 01995 /* Give us access to restore any files we want */ 01996 Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &OldState); 01997 if (NT_SUCCESS(Status)) HavePrivilege = TRUE; 01998 01999 /* Process pending files to rename */ 02000 Head = &SmpFileRenameList; 02001 while (!IsListEmpty(Head)) 02002 { 02003 /* Get this entry */ 02004 NextEntry = RemoveHeadList(Head); 02005 RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry); 02006 DPRINT1("Processing PFRO: %wZ/%wZ\n", &RegEntry->Value, &RegEntry->Name); 02007 02008 /* Skip past the '@' marker */ 02009 if (!(RegEntry->Value.Length) && (*RegEntry->Name.Buffer == L'@')) 02010 { 02011 RegEntry->Name.Length -= sizeof(UNICODE_NULL); 02012 RegEntry->Name.Buffer++; 02013 } 02014 02015 /* Open the file for delete access */ 02016 InitializeObjectAttributes(&ObjectAttributes, 02017 &RegEntry->Name, 02018 OBJ_CASE_INSENSITIVE, 02019 NULL, 02020 NULL); 02021 Status = NtOpenFile(&OtherFileHandle, 02022 DELETE | SYNCHRONIZE, 02023 &ObjectAttributes, 02024 &IoStatusBlock, 02025 FILE_SHARE_READ | FILE_SHARE_WRITE, 02026 FILE_SYNCHRONOUS_IO_NONALERT); 02027 if (!NT_SUCCESS(Status)) goto Quickie; 02028 02029 /* Check if it's a rename or just a delete */ 02030 ValueLength = RegEntry->Value.Length; 02031 if (!ValueLength) 02032 { 02033 /* Just a delete, set up the class, length and buffer */ 02034 InformationClass = FileDispositionInformation; 02035 Length = sizeof(DeleteInformation); 02036 Buffer = (PFILE_RENAME_INFORMATION)&DeleteInformation; 02037 02038 /* Set the delete disposition */ 02039 DeleteInformation.DeleteFile = TRUE; 02040 } 02041 else 02042 { 02043 /* This is a rename, setup the class and length */ 02044 InformationClass = FileRenameInformation; 02045 Length = ValueLength + sizeof(FILE_RENAME_INFORMATION); 02046 02047 /* Skip past the special markers */ 02048 FileName = RegEntry->Value.Buffer; 02049 if ((*FileName == L'!') || (*FileName == L'@')) 02050 { 02051 FileName++; 02052 Length -= sizeof(UNICODE_NULL); 02053 } 02054 02055 /* Now allocate the buffer for the rename information */ 02056 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), SmBaseTag, Length); 02057 if (Buffer) 02058 { 02059 /* Setup the buffer to point to the filename, and copy it */ 02060 Buffer->RootDirectory = NULL; 02061 Buffer->FileNameLength = Length - sizeof(FILE_RENAME_INFORMATION); 02062 Buffer->ReplaceIfExists = FileName != RegEntry->Value.Buffer; 02063 RtlCopyMemory(Buffer->FileName, FileName, Buffer->FileNameLength); 02064 } 02065 else 02066 { 02067 /* Fail */ 02068 Status = STATUS_NO_MEMORY; 02069 } 02070 } 02071 02072 /* Check if everything is okay till here */ 02073 if (NT_SUCCESS(Status)) 02074 { 02075 /* Now either rename or delete the file as requested */ 02076 Status = NtSetInformationFile(OtherFileHandle, 02077 &IoStatusBlock, 02078 Buffer, 02079 Length, 02080 InformationClass); 02081 02082 /* Check if we seem to have failed because the file was readonly */ 02083 if ((NT_SUCCESS(Status) && 02084 (InformationClass == FileRenameInformation) && 02085 (Status == STATUS_OBJECT_NAME_COLLISION) && 02086 (Buffer->ReplaceIfExists))) 02087 { 02088 /* Open the file for write attribute access this time... */ 02089 DPRINT1("\nSMSS: %wZ => %wZ failed - Status == %x, Possible readonly target\n", 02090 &RegEntry->Name, 02091 &RegEntry->Value, 02092 STATUS_OBJECT_NAME_COLLISION); 02093 FileString.Length = RegEntry->Value.Length - sizeof(WCHAR); 02094 FileString.MaximumLength = RegEntry->Value.MaximumLength - sizeof(WCHAR); 02095 FileString.Buffer = FileName; 02096 InitializeObjectAttributes(&ObjectAttributes, 02097 &FileString, 02098 OBJ_CASE_INSENSITIVE, 02099 NULL, 02100 NULL); 02101 Status = NtOpenFile(&FileHandle, 02102 FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, 02103 &ObjectAttributes, 02104 &IoStatusBlock, 02105 FILE_SHARE_READ | FILE_SHARE_WRITE, 02106 FILE_SYNCHRONOUS_IO_NONALERT); 02107 if (!NT_SUCCESS(Status)) 02108 { 02109 /* That didn't work, so bail out */ 02110 DPRINT1(" SMSS: Open Existing file Failed - Status == %x\n", 02111 Status); 02112 } 02113 else 02114 { 02115 /* Now remove the read-only attribute from the file */ 02116 DPRINT1(" SMSS: Open Existing Success\n"); 02117 RtlZeroMemory(&BasicInfo, sizeof(BasicInfo)); 02118 BasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; 02119 Status = NtSetInformationFile(FileHandle, 02120 &IoStatusBlock, 02121 &BasicInfo, 02122 sizeof(BasicInfo), 02123 FileBasicInformation); 02124 NtClose(FileHandle); 02125 if (!NT_SUCCESS(Status)) 02126 { 02127 /* That didn't work, bail out */ 02128 DPRINT1(" SMSS: Set To NORMAL Failed - Status == %x\n", 02129 Status); 02130 } 02131 else 02132 { 02133 /* Now that the file is no longer read-only, delete! */ 02134 DPRINT1(" SMSS: Set To NORMAL OK\n"); 02135 Status = NtSetInformationFile(OtherFileHandle, 02136 &IoStatusBlock, 02137 Buffer, 02138 Length, 02139 FileRenameInformation); 02140 if (!NT_SUCCESS(Status)) 02141 { 02142 /* That failed too! */ 02143 DPRINT1(" SMSS: Re-Rename Failed - Status == %x\n", 02144 Status); 02145 } 02146 else 02147 { 02148 /* Everything ok */ 02149 DPRINT1(" SMSS: Re-Rename Worked OK\n"); 02150 } 02151 } 02152 } 02153 } 02154 } 02155 02156 /* Close the file handle and check the operation result */ 02157 NtClose(OtherFileHandle); 02158 Quickie: 02159 if (!NT_SUCCESS(Status)) 02160 { 02161 /* We totally failed */ 02162 DPRINT1("SMSS: %wZ => %wZ failed - Status == %x\n", 02163 &RegEntry->Name, &RegEntry->Value, Status); 02164 } 02165 else if (RegEntry->Value.Length) 02166 { 02167 /* We succeed with a rename */ 02168 DPRINT1("SMSS: %wZ (renamed to) %wZ\n", &RegEntry->Name, &RegEntry->Value); 02169 } 02170 else 02171 { 02172 /* We suceeded with a delete */ 02173 DPRINT1("SMSS: %wZ (deleted)\n", &RegEntry->Name); 02174 } 02175 02176 /* Now free this entry and keep going */ 02177 if (RegEntry->AnsiValue) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue); 02178 if (RegEntry->Value.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer); 02179 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry); 02180 } 02181 02182 /* Put back the restore privilege if we had requested it, and return */ 02183 if (HavePrivilege) RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, FALSE, FALSE, &OldState); 02184 return Status; 02185 } 02186 02187 NTSTATUS 02188 NTAPI 02189 SmpLoadDataFromRegistry(OUT PUNICODE_STRING InitialCommand) 02190 { 02191 NTSTATUS Status; 02192 PLIST_ENTRY Head, NextEntry; 02193 PSMP_REGISTRY_VALUE RegEntry; 02194 PVOID OriginalEnvironment; 02195 ULONG MuSessionId = 0; 02196 OBJECT_ATTRIBUTES ObjectAttributes; 02197 HANDLE KeyHandle; 02198 UNICODE_STRING DestinationString; 02199 02200 /* Initialize the keywords we'll be looking for */ 02201 RtlInitUnicodeString(&SmpDebugKeyword, L"debug"); 02202 RtlInitUnicodeString(&SmpASyncKeyword, L"async"); 02203 RtlInitUnicodeString(&SmpAutoChkKeyword, L"autocheck"); 02204 02205 /* Initialize all the registry-associated list heads */ 02206 InitializeListHead(&SmpBootExecuteList); 02207 InitializeListHead(&SmpSetupExecuteList); 02208 InitializeListHead(&SmpPagingFileList); 02209 InitializeListHead(&SmpDosDevicesList); 02210 InitializeListHead(&SmpFileRenameList); 02211 InitializeListHead(&SmpKnownDllsList); 02212 InitializeListHead(&SmpExcludeKnownDllsList); 02213 InitializeListHead(&SmpSubSystemList); 02214 InitializeListHead(&SmpSubSystemsToLoad); 02215 InitializeListHead(&SmpSubSystemsToDefer); 02216 InitializeListHead(&SmpExecuteList); 02217 SmpPagingFileInitialize(); 02218 02219 /* Initialize the SMSS environment */ 02220 Status = RtlCreateEnvironment(TRUE, &SmpDefaultEnvironment); 02221 if (!NT_SUCCESS(Status)) 02222 { 02223 /* Fail if there was a problem */ 02224 DPRINT1("SMSS: Unable to allocate default environment - Status == %X\n", 02225 Status); 02226 SMSS_CHECKPOINT(RtlCreateEnvironment, Status); 02227 return Status; 02228 } 02229 02230 /* Check if we were booted in PE mode (LiveCD should have this) */ 02231 RtlInitUnicodeString(&DestinationString, 02232 L"\\Registry\\Machine\\System\\CurrentControlSet\\" 02233 L"Control\\MiniNT"); 02234 InitializeObjectAttributes(&ObjectAttributes, 02235 &DestinationString, 02236 OBJ_CASE_INSENSITIVE, 02237 NULL, 02238 NULL); 02239 Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); 02240 if (NT_SUCCESS(Status)) 02241 { 02242 /* If the key exists, we were */ 02243 NtClose(KeyHandle); 02244 MiniNTBoot = TRUE; 02245 } 02246 02247 /* Print out if this is the case */ 02248 if (MiniNTBoot) DPRINT1("SMSS: !!! MiniNT Boot !!!\n"); 02249 02250 /* Open the environment key to see if we are booted in safe mode */ 02251 RtlInitUnicodeString(&DestinationString, 02252 L"\\Registry\\Machine\\System\\CurrentControlSet\\" 02253 L"Control\\Session Manager\\Environment"); 02254 InitializeObjectAttributes(&ObjectAttributes, 02255 &DestinationString, 02256 OBJ_CASE_INSENSITIVE, 02257 NULL, 02258 NULL); 02259 Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); 02260 if (NT_SUCCESS(Status)) 02261 { 02262 /* Delete the value if we found it */ 02263 RtlInitUnicodeString(&DestinationString, L"SAFEBOOT_OPTION"); 02264 NtDeleteValueKey(KeyHandle, &DestinationString); 02265 NtClose(KeyHandle); 02266 } 02267 02268 /* Switch environments, then query the registry for all needed settings */ 02269 OriginalEnvironment = NtCurrentPeb()->ProcessParameters->Environment; 02270 NtCurrentPeb()->ProcessParameters->Environment = SmpDefaultEnvironment; 02271 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, 02272 L"Session Manager", 02273 SmpRegistryConfigurationTable, 02274 NULL, 02275 NULL); 02276 SmpDefaultEnvironment = NtCurrentPeb()->ProcessParameters->Environment; 02277 NtCurrentPeb()->ProcessParameters->Environment = OriginalEnvironment; 02278 if (!NT_SUCCESS(Status)) 02279 { 02280 /* We failed somewhere in registry initialization, which is bad... */ 02281 DPRINT1("SMSS: RtlQueryRegistryValues failed - Status == %lx\n", Status); 02282 SMSS_CHECKPOINT(RtlQueryRegistryValues, Status); 02283 return Status; 02284 } 02285 02286 /* Now we can start acting on the registry settings. First to DOS devices */ 02287 Status = SmpInitializeDosDevices(); 02288 if (!NT_SUCCESS(Status)) 02289 { 02290 /* Failed */ 02291 DPRINT1("SMSS: Unable to initialize DosDevices configuration - Status == %lx\n", 02292 Status); 02293 SMSS_CHECKPOINT(SmpInitializeDosDevices, Status); 02294 return Status; 02295 } 02296 02297 /* Next create the session directory... */ 02298 RtlInitUnicodeString(&DestinationString, L"\\Sessions"); 02299 InitializeObjectAttributes(&ObjectAttributes, 02300 &DestinationString, 02301 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT, 02302 NULL, 02303 SmpPrimarySecurityDescriptor); 02304 Status = NtCreateDirectoryObject(&SmpSessionsObjectDirectory, 02305 DIRECTORY_ALL_ACCESS, 02306 &ObjectAttributes); 02307 if (!NT_SUCCESS(Status)) 02308 { 02309 /* Fail */ 02310 DPRINT1("SMSS: Unable to create %wZ object directory - Status == %lx\n", 02311 &DestinationString, Status); 02312 SMSS_CHECKPOINT(NtCreateDirectoryObject, Status); 02313 return Status; 02314 } 02315 02316 /* Next loop all the boot execute binaries */ 02317 Head = &SmpBootExecuteList; 02318 while (!IsListEmpty(Head)) 02319 { 02320 /* Remove each one from the list */ 02321 NextEntry = RemoveHeadList(Head); 02322 02323 /* Execute it */ 02324 RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry); 02325 SmpExecuteCommand(&RegEntry->Name, 0, NULL, 0); 02326 02327 /* And free it */ 02328 if (RegEntry->AnsiValue) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue); 02329 if (RegEntry->Value.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer); 02330 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry); 02331 } 02332 02333 /* Now do any pending file rename operations... */ 02334 if (!MiniNTBoot) SmpProcessFileRenames(); 02335 02336 /* And initialize known DLLs... */ 02337 Status = SmpInitializeKnownDlls(); 02338 if (!NT_SUCCESS(Status)) 02339 { 02340 /* Fail if that didn't work */ 02341 DPRINT1("SMSS: Unable to initialize KnownDll configuration - Status == %lx\n", 02342 Status); 02343 SMSS_CHECKPOINT(SmpInitializeKnownDlls, Status); 02344 return Status; 02345 } 02346 02347 /* Loop every page file */ 02348 Head = &SmpPagingFileList; 02349 while (!IsListEmpty(Head)) 02350 { 02351 /* Remove each one from the list */ 02352 NextEntry = RemoveHeadList(Head); 02353 02354 /* Create the descriptor for it */ 02355 RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry); 02356 SmpCreatePagingFileDescriptor(&RegEntry->Name); 02357 02358 /* And free it */ 02359 if (RegEntry->AnsiValue) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue); 02360 if (RegEntry->Value.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer); 02361 RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry); 02362 } 02363 02364 /* Now create all the paging files for the descriptors that we have */ 02365 SmpCreatePagingFiles(); 02366 02367 /* Tell Cm it's now safe to fully enable write access to the registry */ 02368 NtInitializeRegistry(CM_BOOT_FLAG_SMSS); 02369 02370 /* Create all the system-based environment variables for later inheriting */ 02371 Status = SmpCreateDynamicEnvironmentVariables(); 02372 if (!NT_SUCCESS(Status)) 02373 { 02374 /* Handle failure */ 02375 SMSS_CHECKPOINT(SmpCreateDynamicEnvironmentVariables, Status); 02376 return Status; 02377 } 02378 02379 /* And finally load all the subsytems for our first session! */ 02380 Status = SmpLoadSubSystemsForMuSession(&MuSessionId, 02381 &SmpWindowsSubSysProcessId, 02382 InitialCommand); 02383 ASSERT(MuSessionId == 0); 02384 if (!NT_SUCCESS(Status)) SMSS_CHECKPOINT(SmpLoadSubSystemsForMuSession, Status); 02385 return Status; 02386 } 02387 02388 NTSTATUS 02389 NTAPI 02390 SmpInit(IN PUNICODE_STRING InitialCommand, 02391 OUT PHANDLE ProcessHandle) 02392 { 02393 NTSTATUS Status, Status2; 02394 OBJECT_ATTRIBUTES ObjectAttributes; 02395 UNICODE_STRING PortName, EventName; 02396 HANDLE EventHandle, PortHandle; 02397 ULONG HardErrorMode; 02398 02399 /* Create the SMSS Heap */ 02400 SmBaseTag = RtlCreateTagHeap(RtlGetProcessHeap(), 02401 0, 02402 L"SMSS!", 02403 L"INIT"); 02404 SmpHeap = RtlGetProcessHeap(); 02405 02406 /* Enable hard errors */ 02407 HardErrorMode = TRUE; 02408 NtSetInformationProcess(NtCurrentProcess(), 02409 ProcessDefaultHardErrorMode, 02410 &HardErrorMode, 02411 sizeof(HardErrorMode)); 02412 02413 /* Initialize the subsystem list and the session list, plus their locks */ 02414 RtlInitializeCriticalSection(&SmpKnownSubSysLock); 02415 InitializeListHead(&SmpKnownSubSysHead); 02416 RtlInitializeCriticalSection(&SmpSessionListLock); 02417 InitializeListHead(&SmpSessionListHead); 02418 02419 /* Initialize the process list */ 02420 InitializeListHead(&NativeProcessList); 02421 02422 /* Initialize session parameters */ 02423 SmpNextSessionId = 1; 02424 SmpNextSessionIdScanMode = 0; 02425 SmpDbgSsLoaded = FALSE; 02426 02427 /* Create the initial security descriptors */ 02428 Status = SmpCreateSecurityDescriptors(TRUE); 02429 if (!NT_SUCCESS(Status)) 02430 { 02431 /* Fail */ 02432 SMSS_CHECKPOINT(SmpCreateSecurityDescriptors, Status); 02433 return Status; 02434 } 02435 02436 /* Initialize subsystem names */ 02437 RtlInitUnicodeString(&SmpSubsystemName, L"NT-Session Manager"); 02438 RtlInitUnicodeString(&PosixName, L"POSIX"); 02439 RtlInitUnicodeString(&Os2Name, L"OS2"); 02440 02441 /* Create the SM API Port */ 02442 RtlInitUnicodeString(&PortName, L"\\SmApiPort2"); 02443 InitializeObjectAttributes(&ObjectAttributes, &PortName, 0, NULL, NULL); 02444 Status = NtCreatePort(&PortHandle, 02445 &ObjectAttributes, 02446 sizeof(SB_CONNECTION_INFO), 02447 sizeof(SM_API_MSG), 02448 sizeof(SB_API_MSG) * 32); 02449 ASSERT(NT_SUCCESS(Status)); 02450 SmpDebugPort = PortHandle; 02451 02452 /* Create two SM API threads */ 02453 Status = RtlCreateUserThread(NtCurrentProcess(), 02454 NULL, 02455 FALSE, 02456 0, 02457 0, 02458 0, 02459 SmpApiLoop, 02460 PortHandle, 02461 NULL, 02462 NULL); 02463 ASSERT(NT_SUCCESS(Status)); 02464 Status = RtlCreateUserThread(NtCurrentProcess(), 02465 NULL, 02466 FALSE, 02467 0, 02468 0, 02469 0, 02470 SmpApiLoop, 02471 PortHandle, 02472 NULL, 02473 NULL); 02474 ASSERT(NT_SUCCESS(Status)); 02475 02476 /* Create the write event that autochk can set after running */ 02477 RtlInitUnicodeString(&EventName, L"\\Device\\VolumesSafeForWriteAccess"); 02478 InitializeObjectAttributes(&ObjectAttributes, 02479 &EventName, 02480 OBJ_PERMANENT, 02481 NULL, 02482 NULL); 02483 Status2 = NtCreateEvent(&EventHandle, 02484 EVENT_ALL_ACCESS, 02485 &ObjectAttributes, 02486 0, 02487 0); 02488 if (!NT_SUCCESS(Status2)) 02489 { 02490 /* Should never really fail */ 02491 DPRINT1("SMSS: Unable to create %wZ event - Status == %lx\n", 02492 &EventName, Status2); 02493 ASSERT(NT_SUCCESS(Status2)); 02494 } 02495 02496 /* Now initialize everything else based on the registry parameters */ 02497 Status = SmpLoadDataFromRegistry(InitialCommand); 02498 if (NT_SUCCESS(Status)) 02499 { 02500 /* Autochk should've run now. Set the event and save the CSRSS handle */ 02501 *ProcessHandle = SmpWindowsSubSysProcess; 02502 NtSetEvent(EventHandle, 0); 02503 NtClose(EventHandle); 02504 } 02505 02506 /* All done */ 02507 return Status; 02508 } Generated on Sun May 27 2012 04:18:53 for ReactOS by
1.7.6.1
|