ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

sminit.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.