ReactOS  0.4.11-dev-721-g95bc44e
sminit.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Windows-Compatible Session Manager
3  * LICENSE: BSD 2-Clause License
4  * FILE: base/system/smss/sminit.c
5  * PURPOSE: Main SMSS Code
6  * PROGRAMMERS: Alex Ionescu
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "smss.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* GLOBALS ********************************************************************/
17 
23 
30 
34 
39 
42 
43 #define SMSS_CHECKPOINT(x, y) \
44 { \
45  SmpInitProgressByLine = __LINE__; \
46  SmpInitReturnStatus = (y); \
47  SmpInitLastCall = (x); \
48 }
49 
50 /* REGISTRY CONFIGURATION *****************************************************/
51 
53 NTAPI
55  IN PWSTR Name,
56  IN PWCHAR Value,
58 {
60  UNICODE_STRING NameString, ValueString;
61  ANSI_STRING AnsiValueString;
62  PLIST_ENTRY NextEntry;
63 
64  /* Convert to unicode strings */
65  RtlInitUnicodeString(&NameString, Name);
66  RtlInitUnicodeString(&ValueString, Value);
67 
68  /* In case this is the first value, initialize a new list/structure */
69  RegEntry = NULL;
70 
71  /* Check if we should do a duplicate check */
72  if (Flags)
73  {
74  /* Loop the current list */
75  NextEntry = ListAddress->Flink;
76  while (NextEntry != ListAddress)
77  {
78  /* Get each entry */
79  RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
80 
81  /* Check if the value name matches */
82  if (!RtlCompareUnicodeString(&RegEntry->Name, &NameString, TRUE))
83  {
84  /* Check if the value is the exact same thing */
85  if (!RtlCompareUnicodeString(&RegEntry->Value, &ValueString, TRUE))
86  {
87  /* Fail -- the same setting is being set twice */
89  }
90 
91  /* We found the list, and this isn't a duplicate value */
92  break;
93  }
94 
95  /* This wasn't a match, keep going */
96  NextEntry = NextEntry->Flink;
97  RegEntry = NULL;
98  }
99  }
100 
101  /* Are we adding on, or creating a new entry */
102  if (!RegEntry)
103  {
104  /* A new entry -- allocate it */
105  RegEntry = RtlAllocateHeap(RtlGetProcessHeap(),
106  SmBaseTag,
107  sizeof(SMP_REGISTRY_VALUE) +
108  NameString.MaximumLength);
109  if (!RegEntry) return STATUS_NO_MEMORY;
110 
111  /* Initialize the list and set all values to NULL */
112  InitializeListHead(&RegEntry->Entry);
113  RegEntry->AnsiValue = NULL;
114  RegEntry->Value.Buffer = NULL;
115 
116  /* Copy and initialize the value name */
117  RegEntry->Name.Buffer = (PWCHAR)(RegEntry + 1);
118  RegEntry->Name.Length = NameString.Length;
119  RegEntry->Name.MaximumLength = NameString.MaximumLength;
120  RtlCopyMemory(RegEntry->Name.Buffer,
121  NameString.Buffer,
122  NameString.MaximumLength);
123 
124  /* Add this entry into the list */
125  InsertTailList(ListAddress, &RegEntry->Entry);
126  }
127 
128  /* Did we have an old value buffer? */
129  if (RegEntry->Value.Buffer)
130  {
131  /* Free it */
132  ASSERT(RegEntry->Value.Length != 0);
133  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer);
134  }
135 
136  /* Is there no value associated? */
137  if (!Value)
138  {
139  /* We're done here */
140  RtlInitUnicodeString(&RegEntry->Value, NULL);
141  return STATUS_SUCCESS;
142  }
143 
144  /* There is a value, so allocate a buffer for it */
145  RegEntry->Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
146  SmBaseTag,
147  ValueString.MaximumLength);
148  if (!RegEntry->Value.Buffer)
149  {
150  /* Out of memory, undo */
151  RemoveEntryList(&RegEntry->Entry);
152  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry);
153  return STATUS_NO_MEMORY;
154  }
155 
156  /* Copy the value into the entry */
157  RegEntry->Value.Length = ValueString.Length;
158  RegEntry->Value.MaximumLength = ValueString.MaximumLength;
159  RtlCopyMemory(RegEntry->Value.Buffer,
160  ValueString.Buffer,
161  ValueString.MaximumLength);
162 
163  /* Now allocate memory for an ANSI copy of it */
164  RegEntry->AnsiValue = RtlAllocateHeap(RtlGetProcessHeap(),
165  SmBaseTag,
166  (ValueString.Length / sizeof(WCHAR)) +
167  sizeof(ANSI_NULL));
168  if (!RegEntry->AnsiValue)
169  {
170  /* Out of memory, undo */
171  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer);
172  RemoveEntryList(&RegEntry->Entry);
173  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry);
174  return STATUS_NO_MEMORY;
175  }
176 
177  /* Convert the Unicode value string and return success */
178  RtlInitEmptyAnsiString(&AnsiValueString,
179  RegEntry->AnsiValue,
180  (ValueString.Length / sizeof(WCHAR)) +
181  sizeof(ANSI_NULL));
182  RtlUnicodeStringToAnsiString(&AnsiValueString, &ValueString, FALSE);
183  return STATUS_SUCCESS;
184 }
185 
187 NTAPI
190 {
192  UNICODE_STRING ValueString;
193  PLIST_ENTRY NextEntry;
194 
195  /* Initialize the value name sting */
196  RtlInitUnicodeString(&ValueString, ValueName);
197 
198  /* Loop the list */
199  NextEntry = List->Flink;
200  while (NextEntry != List)
201  {
202  /* Get each entry */
203  RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
204 
205  /* Check if the value name matches */
206  if (!RtlCompareUnicodeString(&RegEntry->Name, &ValueString, TRUE)) break;
207 
208  /* It doesn't, move on */
209  NextEntry = NextEntry->Flink;
210  }
211 
212  /* If we looped back, return NULL, otherwise return the entry we found */
213  if (NextEntry == List) RegEntry = NULL;
214  return RegEntry;
215 }
216 
217 NTSTATUS
218 NTAPI
223  IN PVOID Context,
225 {
226  /* Make sure the value is valid */
227  if (ValueLength == sizeof(ULONG))
228  {
229  /* Read it */
230  SmpProtectionMode = *(PULONG)ValueData;
231  }
232  else
233  {
234  /* Default is to protect stuff */
235  SmpProtectionMode = 1;
236  }
237 
238  /* Recreate the security descriptors to take into account security mode */
240  DPRINT("SmpProtectionMode: %lu\n", SmpProtectionMode);
241  return STATUS_SUCCESS;
242 }
243 
244 NTSTATUS
245 NTAPI
250  IN PVOID Context,
252 {
253  /* Make sure the value is valid */
254  if (ValueLength == sizeof(ULONG))
255  {
256  /* Read it */
257  SmpAllowProtectedRenames = *(PULONG)ValueData;
258  }
259  else
260  {
261  /* Default is to not allow protected renames */
263  }
264 
265  DPRINT("SmpAllowProtectedRenames: %lu\n", SmpAllowProtectedRenames);
266  return STATUS_SUCCESS;
267 }
268 
269 NTSTATUS
270 NTAPI
275  IN PVOID Context,
277 {
278  PISECURITY_DESCRIPTOR SecDescriptor;
281  HANDLE DirHandle;
282  UNICODE_STRING RpcString, WindowsString, SearchString;
284 
285  /* Initialize the two strings we will be looking for */
286  RtlInitUnicodeString(&RpcString, L"\\RPC Control");
287  RtlInitUnicodeString(&WindowsString, L"\\Windows");
288 
289  /* Loop the registry data we received */
290  while (*SourceString)
291  {
292  /* Assume primary SD for most objects */
293  RtlInitUnicodeString(&SearchString, SourceString);
294  SecDescriptor = SmpPrimarySecurityDescriptor;
295 
296  /* But for these two always set the liberal descriptor */
297  if ((RtlEqualUnicodeString(&SearchString, &RpcString, TRUE)) ||
298  (RtlEqualUnicodeString(&SearchString, &WindowsString, TRUE)))
299  {
300  SecDescriptor = SmpLiberalSecurityDescriptor;
301  }
302 
303  /* Create the requested directory with the requested descriptor */
304  InitializeObjectAttributes(&ObjectAttributes,
305  &SearchString,
307  OBJ_OPENIF |
309  NULL,
310  SecDescriptor);
311  DPRINT("Creating: %wZ directory\n", &SearchString);
312  Status = NtCreateDirectoryObject(&DirHandle,
314  &ObjectAttributes);
315  if (!NT_SUCCESS(Status))
316  {
317  /* Failure case */
318  DPRINT1("SMSS: Unable to create %wZ object directory - Status == %lx\n",
319  &SearchString, Status);
320  }
321  else
322  {
323  /* It worked, now close the handle */
324  NtClose(DirHandle);
325  }
326 
327  /* Move to the next requested object */
328  SourceString += wcslen(SourceString) + 1;
329  }
330 
331  /* All done */
332  return STATUS_SUCCESS;
333 }
334 
335 NTSTATUS
336 NTAPI
341  IN PVOID Context,
343 {
344  /* Save this is into a list */
345  return SmpSaveRegistryValue(EntryContext, ValueData, NULL, TRUE);
346 }
347 
348 NTSTATUS
349 NTAPI
354  IN PVOID Context,
356 {
358  static PWCHAR Canary = NULL;
359 
360  /* Check if this is the second call */
361  if (Canary)
362  {
363  /* Save the data into the list */
364  DPRINT("Renamed file: '%S' - '%S'\n", Canary, ValueData);
365  Status = SmpSaveRegistryValue(EntryContext, Canary, ValueData, FALSE);
366  Canary = NULL;
367  }
368  else
369  {
370  /* This it the first call, do nothing until we get the second call */
371  Canary = ValueData;
372  Status = STATUS_SUCCESS;
373  }
374 
375  /* Return the status */
376  return Status;
377 }
378 
379 NTSTATUS
380 NTAPI
385  IN PVOID Context,
387 {
388  PWCHAR DllName;
390 
391  /* Make sure the value type is valid */
392  if ((ValueType == REG_MULTI_SZ) || (ValueType == REG_SZ))
393  {
394  /* Keep going for each DLL in the list */
395  DllName = ValueData;
396  while (*DllName)
397  {
398  /* Add this to the linked list */
399  DPRINT("Excluded DLL: %S\n", DllName);
400  Status = SmpSaveRegistryValue(EntryContext, DllName, NULL, TRUE);
401 
402  /* Bail out on failure or if only one DLL name was present */
403  if (!(NT_SUCCESS(Status)) || (ValueType == REG_SZ)) return Status;
404 
405  /* Otherwise, move to the next DLL name */
406  DllName += wcslen(DllName) + 1;
407  }
408  }
409 
410  /* All done */
411  return STATUS_SUCCESS;
412 }
413 
414 NTSTATUS
415 NTAPI
420  IN PVOID Context,
422 {
423  /* Save into linked list */
424  return SmpSaveRegistryValue(EntryContext, ValueName, ValueData, TRUE);
425 }
426 
427 NTSTATUS
428 NTAPI
430  IN PWCHAR Buffer,
431  IN ULONG Length)
432 {
434 
435  /* Allocate the buffer */
436  DllPath->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), SmBaseTag, Length);
437  if (DllPath->Buffer)
438  {
439  /* Fill out the rest of the string */
440  DllPath->MaximumLength = (USHORT)Length;
441  DllPath->Length = (USHORT)Length - sizeof(UNICODE_NULL);
442 
443  /* Copy the actual path and return success */
444  RtlCopyMemory(DllPath->Buffer, Buffer, Length);
445  Status = STATUS_SUCCESS;
446  }
447  else
448  {
449  /* Fail with out of memory code */
450  Status = STATUS_NO_MEMORY;
451  }
452 
453  /* Return result */
454  return Status;
455 }
456 
457 NTSTATUS
458 NTAPI
463  IN PVOID Context,
465 {
466  /* Check which value is being set */
467  if (_wcsicmp(ValueName, L"DllDirectory") == 0)
468  {
469  /* This is the directory, initialize it */
470  DPRINT("KnownDll Path: %S\n", ValueData);
471  return SmpInitializeKnownDllPath(&SmpKnownDllPath, ValueData, ValueLength);
472  }
473  else
474  {
475  /* Add to the linked list -- this is a file */
476  return SmpSaveRegistryValue(EntryContext, ValueName, ValueData, TRUE);
477  }
478 }
479 
480 NTSTATUS
481 NTAPI
486  IN PVOID Context,
488 {
490  UNICODE_STRING ValueString, DataString;
491 
492  /* Convert the strings into UNICODE_STRING and set the variable defined */
493  RtlInitUnicodeString(&ValueString, ValueName);
494  RtlInitUnicodeString(&DataString, ValueData);
495  DPRINT("Setting %wZ = %wZ\n", &ValueString, &DataString);
496  Status = RtlSetEnvironmentVariable(0, &ValueString, &DataString);
497  if (!NT_SUCCESS(Status))
498  {
499  DPRINT1("SMSS: 'SET %wZ = %wZ' failed - Status == %lx\n",
500  &ValueString, &DataString, Status);
501  return Status;
502  }
503 
504  /* Check if the path is being set, and wait for the second instantiation */
505  if ((_wcsicmp(ValueName, L"Path") == 0) && (++SmpCalledConfigEnv == 2))
506  {
507  /* Allocate the path buffer */
508  SmpDefaultLibPathBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
509  SmBaseTag,
510  ValueLength);
512 
513  /* Copy the data into it and create the UNICODE_STRING to hold it */
514  RtlCopyMemory(SmpDefaultLibPathBuffer, ValueData, ValueLength);
515  RtlInitUnicodeString(&SmpDefaultLibPath, SmpDefaultLibPathBuffer);
516  }
517 
518  /* All good */
519  return STATUS_SUCCESS;
520 }
521 
522 NTSTATUS
523 NTAPI
528  IN PVOID Context,
530 {
532  PWCHAR SubsystemName;
533 
534  /* Is this a required or optional subsystem? */
535  if ((_wcsicmp(ValueName, L"Required") != 0) &&
536  (_wcsicmp(ValueName, L"Optional") != 0))
537  {
538  /* It isn't, is this the PSI flag? */
539  if ((_wcsicmp(ValueName, L"PosixSingleInstance") != 0) ||
540  (ValueType != REG_DWORD))
541  {
542  /* It isn't, must be a subsystem entry, add it to the list */
543  DPRINT("Subsystem entry: %S-%S\n", ValueName, ValueData);
544  return SmpSaveRegistryValue(EntryContext, ValueName, ValueData, TRUE);
545  }
546 
547  /* This was the PSI flag, save it and exit */
549  return STATUS_SUCCESS;
550  }
551 
552  /* This should be one of the required/optional lists. Is the type valid? */
553  if (ValueType == REG_MULTI_SZ)
554  {
555  /* It is, get the first subsystem */
556  SubsystemName = ValueData;
557  while (*SubsystemName)
558  {
559  /* We should have already put it into the list when we found it */
560  DPRINT("Found subsystem: %S\n", SubsystemName);
561  RegEntry = SmpFindRegistryValue(EntryContext, SubsystemName);
562  if (!RegEntry)
563  {
564  /* This subsystem doesn't exist, so skip it */
565  DPRINT1("SMSS: Invalid subsystem name - %ws\n", SubsystemName);
566  }
567  else
568  {
569  /* Found it -- remove it from the main list */
570  RemoveEntryList(&RegEntry->Entry);
571 
572  /* Figure out which list to put it in */
573  if (_wcsicmp(ValueName, L"Required") == 0)
574  {
575  /* Put it into the required list */
576  DPRINT("Required\n");
577  InsertTailList(&SmpSubSystemsToLoad, &RegEntry->Entry);
578  }
579  else
580  {
581  /* Put it into the optional list */
582  DPRINT("Optional\n");
583  InsertTailList(&SmpSubSystemsToDefer, &RegEntry->Entry);
584  }
585  }
586 
587  /* Move to the next name */
588  SubsystemName += wcslen(SubsystemName) + 1;
589  }
590  }
591 
592  /* All done! */
593  return STATUS_SUCCESS;
594 }
595 
598 {
599  {
601  0,
602  L"ProtectionMode",
603  NULL,
604  REG_DWORD,
605  NULL,
606  0
607  },
608 
609  {
612  L"AllowProtectedRenames",
613  NULL,
614  REG_DWORD,
615  NULL,
616  0
617  },
618 
619  {
621  0,
622  L"ObjectDirectories",
623  NULL,
624  REG_MULTI_SZ,
625  L"\\Windows\0\\RPC Control\0",
626  0
627  },
628 
629  {
631  0,
632  L"BootExecute",
634  REG_MULTI_SZ,
635  L"autocheck AutoChk.exe *\0",
636  0
637  },
638 
639  {
642  L"SetupExecute",
644  REG_NONE,
645  NULL,
646  0
647  },
648 
649  {
652  L"PendingFileRenameOperations",
654  REG_NONE,
655  NULL,
656  0
657  },
658 
659  {
662  L"PendingFileRenameOperations2",
664  REG_NONE,
665  NULL,
666  0
667  },
668 
669  {
671  0,
672  L"ExcludeFromKnownDlls",
674  REG_MULTI_SZ,
675  L"\0",
676  0
677  },
678 
679  {
680  NULL,
682  L"Memory Management",
683  NULL,
684  REG_NONE,
685  NULL,
686  0
687  },
688 
689  {
691  0,
692  L"PagingFiles",
694  REG_MULTI_SZ,
695  L"?:\\pagefile.sys\0",
696  0
697  },
698 
699  {
702  L"DOS Devices",
704  REG_NONE,
705  NULL,
706  0
707  },
708 
709  {
712  L"KnownDlls",
714  REG_NONE,
715  NULL,
716  0
717  },
718 
719  {
722  L"Environment",
723  NULL,
724  REG_NONE,
725  NULL,
726  0
727  },
728 
729  {
732  L"SubSystems",
734  REG_NONE,
735  NULL,
736  0
737  },
738 
739  {
742  L"Required",
744  REG_MULTI_SZ,
745  L"Debug\0Windows\0",
746  0
747  },
748 
749  {
752  L"Optional",
754  REG_NONE,
755  NULL,
756  0
757  },
758 
759  {
761  0,
762  L"Kmode",
764  REG_NONE,
765  NULL,
766  0
767  },
768 
769  {
772  L"Execute",
774  REG_NONE,
775  NULL,
776  0
777  },
778 
779  {0},
780 };
781 
782 /* FUNCTIONS ******************************************************************/
783 
784 VOID
785 NTAPI
787 {
789  UNICODE_STRING UnicodeString, LinkTarget, SearchString, SystemPartition;
791  HANDLE KeyHandle, LinkHandle;
792  CHAR ValueBuffer[512 + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
793  PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)ValueBuffer;
795  CHAR DirInfoBuffer[512 + sizeof(OBJECT_DIRECTORY_INFORMATION)];
796  POBJECT_DIRECTORY_INFORMATION DirInfo = (PVOID)DirInfoBuffer;
797  WCHAR LinkBuffer[MAX_PATH];
798 
799  /* Open the setup key */
800  RtlInitUnicodeString(&UnicodeString, L"\\Registry\\Machine\\System\\Setup");
801  InitializeObjectAttributes(&ObjectAttributes,
802  &UnicodeString,
804  NULL,
805  NULL);
806  Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
807  if (!NT_SUCCESS(Status))
808  {
809  DPRINT1("SMSS: can't open system setup key for reading: 0x%x\n", Status);
810  return;
811  }
812 
813  /* Query the system partition */
814  RtlInitUnicodeString(&UnicodeString, L"SystemPartition");
815  Status = NtQueryValueKey(KeyHandle,
816  &UnicodeString,
818  PartialInfo,
819  sizeof(ValueBuffer),
820  &Length);
821  NtClose(KeyHandle);
822  if (!NT_SUCCESS(Status))
823  {
824  DPRINT1("SMSS: can't query SystemPartition value: 0x%x\n", Status);
825  return;
826  }
827 
828  /* Initialize the system partition string string */
829  RtlInitUnicodeString(&SystemPartition, (PWCHAR)PartialInfo->Data);
830 
831  /* Enumerate the directory looking for the symbolic link string */
832  RtlInitUnicodeString(&SearchString, L"SymbolicLink");
833  RtlInitEmptyUnicodeString(&LinkTarget, LinkBuffer, sizeof(LinkBuffer));
835  DirInfo,
836  sizeof(DirInfoBuffer),
837  TRUE,
838  TRUE,
839  &Context,
840  NULL);
841  if (!NT_SUCCESS(Status))
842  {
843  DPRINT1("SMSS: can't find drive letter for system partition\n");
844  return;
845  }
846 
847  /* Keep searching until we find it */
848  do
849  {
850  /* Is this it? */
851  if ((RtlEqualUnicodeString(&DirInfo->TypeName, &SearchString, TRUE)) &&
852  (DirInfo->Name.Length == 2 * sizeof(WCHAR)) &&
853  (DirInfo->Name.Buffer[1] == L':'))
854  {
855  /* Looks like we found it, open the link to get its target */
856  InitializeObjectAttributes(&ObjectAttributes,
857  &DirInfo->Name,
860  NULL);
861  Status = NtOpenSymbolicLinkObject(&LinkHandle,
863  &ObjectAttributes);
864  if (NT_SUCCESS(Status))
865  {
866  /* Open worked, query the target now */
867  Status = NtQuerySymbolicLinkObject(LinkHandle,
868  &LinkTarget,
869  NULL);
870  NtClose(LinkHandle);
871 
872  /* Check if it matches the string we had found earlier */
873  if ((NT_SUCCESS(Status)) &&
874  ((RtlEqualUnicodeString(&SystemPartition,
875  &LinkTarget,
876  TRUE)) ||
877  ((RtlPrefixUnicodeString(&SystemPartition,
878  &LinkTarget,
879  TRUE)) &&
880  (LinkTarget.Buffer[SystemPartition.Length / sizeof(WCHAR)] == L'\\'))))
881  {
882  /* All done */
883  break;
884  }
885  }
886  }
887 
888  /* Couldn't find it, try again */
890  DirInfo,
891  sizeof(DirInfoBuffer),
892  TRUE,
893  FALSE,
894  &Context,
895  NULL);
896  } while (NT_SUCCESS(Status));
897  if (!NT_SUCCESS(Status))
898  {
899  DPRINT1("SMSS: can't find drive letter for system partition\n");
900  return;
901  }
902 
903  /* Open the setup key again, for full access this time */
904  RtlInitUnicodeString(&UnicodeString,
905  L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup");
906  InitializeObjectAttributes(&ObjectAttributes,
907  &UnicodeString,
909  NULL,
910  NULL);
911  Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
912  if (!NT_SUCCESS(Status))
913  {
914  DPRINT1("SMSS: can't open software setup key for writing: 0x%x\n",
915  Status);
916  return;
917  }
918 
919  /* Wrap up the end of the link buffer */
920  wcsncpy(LinkBuffer, DirInfo->Name.Buffer, 2);
921  LinkBuffer[2] = L'\\';
922  LinkBuffer[3] = L'\0';
923 
924  /* Now set this as the "BootDir" */
925  RtlInitUnicodeString(&UnicodeString, L"BootDir");
926  Status = NtSetValueKey(KeyHandle,
927  &UnicodeString,
928  0,
929  REG_SZ,
930  LinkBuffer,
931  4 * sizeof(WCHAR));
932  if (!NT_SUCCESS(Status))
933  {
934  DPRINT1("SMSS: couldn't write BootDir value: 0x%x\n", Status);
935  }
936  NtClose(KeyHandle);
937 }
938 
939 NTSTATUS
940 NTAPI
942 {
944  PSID WorldSid = NULL, AdminSid = NULL, SystemSid = NULL;
945  PSID RestrictedSid = NULL, OwnerSid = NULL;
949  ULONG AclLength, SidLength;
950  PACL Acl;
952  BOOLEAN ProtectionRequired = FALSE;
953 
954  /* Check if this is the first call */
955  if (InitialCall)
956  {
957  /* Create and set the primary descriptor */
958  SmpPrimarySecurityDescriptor = &SmpPrimarySDBody;
959  Status = RtlCreateSecurityDescriptor(SmpPrimarySecurityDescriptor,
961  ASSERT(NT_SUCCESS(Status));
962  Status = RtlSetDaclSecurityDescriptor(SmpPrimarySecurityDescriptor,
963  TRUE,
964  NULL,
965  FALSE);
966  ASSERT(NT_SUCCESS(Status));
967 
968  /* Create and set the liberal descriptor */
969  SmpLiberalSecurityDescriptor = &SmpLiberalSDBody;
970  Status = RtlCreateSecurityDescriptor(SmpLiberalSecurityDescriptor,
972  ASSERT(NT_SUCCESS(Status));
973  Status = RtlSetDaclSecurityDescriptor(SmpLiberalSecurityDescriptor,
974  TRUE,
975  NULL,
976  FALSE);
977  ASSERT(NT_SUCCESS(Status));
978 
979  /* Create and set the \KnownDlls descriptor */
980  SmpKnownDllsSecurityDescriptor = &SmpKnownDllsSDBody;
981  Status = RtlCreateSecurityDescriptor(SmpKnownDllsSecurityDescriptor,
983  ASSERT(NT_SUCCESS(Status));
984  Status = RtlSetDaclSecurityDescriptor(SmpKnownDllsSecurityDescriptor,
985  TRUE,
986  NULL,
987  FALSE);
988  ASSERT(NT_SUCCESS(Status));
989 
990  /* Create and Set the \ApiPort descriptor */
991  SmpApiPortSecurityDescriptor = &SmpApiPortSDBody;
992  Status = RtlCreateSecurityDescriptor(SmpApiPortSecurityDescriptor,
994  ASSERT(NT_SUCCESS(Status));
995  Status = RtlSetDaclSecurityDescriptor(SmpApiPortSecurityDescriptor,
996  TRUE,
997  NULL,
998  FALSE);
999  ASSERT(NT_SUCCESS(Status));
1000  }
1001 
1002  /* Check if protection was requested in the registry (on by default) */
1003  if (SmpProtectionMode & 1) ProtectionRequired = TRUE;
1004 
1005  /* Exit if there's nothing to do */
1006  if (!(InitialCall || ProtectionRequired)) return STATUS_SUCCESS;
1007 
1008  /* Build the world SID */
1009  Status = RtlAllocateAndInitializeSid(&WorldAuthority, 1,
1011  0, 0, 0, 0, 0, 0, 0,
1012  &WorldSid);
1013  if (!NT_SUCCESS(Status))
1014  {
1015  WorldSid = NULL;
1016  goto Quickie;
1017  }
1018 
1019  /* Build the admin SID */
1020  Status = RtlAllocateAndInitializeSid(&NtAuthority, 2,
1023  0, 0, 0, 0, 0, 0,
1024  &AdminSid);
1025  if (!NT_SUCCESS(Status))
1026  {
1027  AdminSid = NULL;
1028  goto Quickie;
1029  }
1030 
1031  /* Build the owner SID */
1032  Status = RtlAllocateAndInitializeSid(&CreatorAuthority, 1,
1034  0, 0, 0, 0, 0, 0, 0,
1035  &OwnerSid);
1036  if (!NT_SUCCESS(Status))
1037  {
1038  OwnerSid = NULL;
1039  goto Quickie;
1040  }
1041 
1042  /* Build the restricted SID */
1043  Status = RtlAllocateAndInitializeSid(&NtAuthority, 1,
1045  0, 0, 0, 0, 0, 0, 0,
1046  &RestrictedSid);
1047  if (!NT_SUCCESS(Status))
1048  {
1049  RestrictedSid = NULL;
1050  goto Quickie;
1051  }
1052 
1053  /* Build the system SID */
1054  Status = RtlAllocateAndInitializeSid(&NtAuthority, 1,
1056  0, 0, 0, 0, 0, 0, 0,
1057  &SystemSid);
1058  if (!NT_SUCCESS(Status))
1059  {
1060  SystemSid = NULL;
1061  goto Quickie;
1062  }
1063 
1064  /* Now check if we're creating the core descriptors */
1065  if (!InitialCall)
1066  {
1067  /* We're skipping NextAcl so we have to do this here */
1068  SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(RestrictedSid) + RtlLengthSid(AdminSid);
1069  SidLength *= 2;
1070  goto NotInitial;
1071  }
1072 
1073  /* Allocate an ACL with two ACEs with two SIDs each */
1074  SidLength = RtlLengthSid(SystemSid) + RtlLengthSid(AdminSid);
1075  AclLength = sizeof(ACL) + 2 * sizeof(ACCESS_ALLOWED_ACE) + SidLength;
1076  Acl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclLength);
1077  if (!Acl) Status = STATUS_NO_MEMORY;
1078  if (!NT_SUCCESS(Status)) goto NextAcl;
1079 
1080  /* Now build the ACL and add the two ACEs */
1081  Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION2);
1082  ASSERT(NT_SUCCESS(Status));
1083  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid);
1084  ASSERT(NT_SUCCESS(Status));
1085  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, SystemSid);
1086  ASSERT(NT_SUCCESS(Status));
1087 
1088  /* Set this as the DACL */
1089  Status = RtlSetDaclSecurityDescriptor(SmpApiPortSecurityDescriptor,
1090  TRUE,
1091  Acl,
1092  FALSE);
1093  ASSERT(NT_SUCCESS(Status));
1094 
1095 NextAcl:
1096  /* Allocate an ACL with 6 ACEs, two ACEs per SID */
1097  SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(RestrictedSid) + RtlLengthSid(AdminSid);
1098  SidLength *= 2;
1099  AclLength = sizeof(ACL) + 6 * sizeof(ACCESS_ALLOWED_ACE) + SidLength;
1100  Acl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclLength);
1101  if (!Acl) Status = STATUS_NO_MEMORY;
1102  if (!NT_SUCCESS(Status)) goto NotInitial;
1103 
1104  /* Now build the ACL and add the six ACEs */
1105  Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION2);
1106  ASSERT(NT_SUCCESS(Status));
1107  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE, WorldSid);
1108  ASSERT(NT_SUCCESS(Status));
1109  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE, RestrictedSid);
1110  ASSERT(NT_SUCCESS(Status));
1111  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid);
1112  ASSERT(NT_SUCCESS(Status));
1114  ASSERT(NT_SUCCESS(Status));
1116  ASSERT(NT_SUCCESS(Status));
1117  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid);
1118  ASSERT(NT_SUCCESS(Status));
1119 
1120  /* Now edit the last three ACEs and make them inheritable */
1121  Status = RtlGetAce(Acl, 3, (PVOID)&Ace);
1122  ASSERT(NT_SUCCESS(Status));
1124  Status = RtlGetAce(Acl, 4, (PVOID)&Ace);
1125  ASSERT(NT_SUCCESS(Status));
1127  Status = RtlGetAce(Acl, 5, (PVOID)&Ace);
1128  ASSERT(NT_SUCCESS(Status));
1130 
1131  /* Set this as the DACL */
1132  Status = RtlSetDaclSecurityDescriptor(SmpKnownDllsSecurityDescriptor,
1133  TRUE,
1134  Acl,
1135  FALSE);
1136  ASSERT(NT_SUCCESS(Status));
1137 
1138 NotInitial:
1139  /* The initial ACLs have been created, are we also protecting objects? */
1140  if (!ProtectionRequired) goto Quickie;
1141 
1142  /* Allocate an ACL with 7 ACEs, two ACEs per SID, and one final owner ACE */
1143  SidLength += RtlLengthSid(OwnerSid);
1144  AclLength = sizeof(ACL) + 7 * sizeof (ACCESS_ALLOWED_ACE) + 2 * SidLength;
1145  Acl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclLength);
1146  if (!Acl) Status = STATUS_NO_MEMORY;
1147  if (!NT_SUCCESS(Status)) goto Quickie;
1148 
1149  /* Build the ACL and add the seven ACEs */
1150  Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION2);
1151  ASSERT(NT_SUCCESS(Status));
1153  ASSERT(NT_SUCCESS(Status));
1154  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ, RestrictedSid);
1155  ASSERT(NT_SUCCESS(Status));
1156  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid);
1157  ASSERT(NT_SUCCESS(Status));
1159  ASSERT(NT_SUCCESS(Status));
1160  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ, RestrictedSid);
1161  ASSERT(NT_SUCCESS(Status));
1162  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid);
1163  ASSERT(NT_SUCCESS(Status));
1164  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, OwnerSid);
1165  ASSERT(NT_SUCCESS(Status));
1166 
1167  /* Edit the last 4 ACEs to make then inheritable */
1168  Status = RtlGetAce(Acl, 3, (PVOID)&Ace);
1169  ASSERT(NT_SUCCESS(Status));
1171  Status = RtlGetAce(Acl, 4, (PVOID)&Ace);
1172  ASSERT(NT_SUCCESS(Status));
1174  Status = RtlGetAce(Acl, 5, (PVOID)&Ace);
1175  ASSERT(NT_SUCCESS(Status));
1177  Status = RtlGetAce(Acl, 6, (PVOID)&Ace);
1178  ASSERT(NT_SUCCESS(Status));
1180 
1181  /* Set this as the DACL for the primary SD */
1182  Status = RtlSetDaclSecurityDescriptor(SmpPrimarySecurityDescriptor,
1183  TRUE,
1184  Acl,
1185  FALSE);
1186  ASSERT(NT_SUCCESS(Status));
1187 
1188  /* Allocate an ACL with 7 ACEs, two ACEs per SID, and one final owner ACE */
1189  AclLength = sizeof(ACL) + 7 * sizeof (ACCESS_ALLOWED_ACE) + 2 * SidLength;
1190  Acl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclLength);
1191  if (!Acl) Status = STATUS_NO_MEMORY;
1192  if (!NT_SUCCESS(Status)) goto Quickie;
1193 
1194  /* Build the ACL and add the seven ACEs */
1195  Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION2);
1196  ASSERT(NT_SUCCESS(Status));
1198  ASSERT(NT_SUCCESS(Status));
1200  ASSERT(NT_SUCCESS(Status));
1201  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid);
1202  ASSERT(NT_SUCCESS(Status));
1204  ASSERT(NT_SUCCESS(Status));
1206  ASSERT(NT_SUCCESS(Status));
1207  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, AdminSid);
1208  ASSERT(NT_SUCCESS(Status));
1209  Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION2, GENERIC_ALL, OwnerSid);
1210  ASSERT(NT_SUCCESS(Status));
1211 
1212  /* Edit the last 4 ACEs to make then inheritable */
1213  Status = RtlGetAce(Acl, 3, (PVOID)&Ace);
1214  ASSERT(NT_SUCCESS(Status));
1216  Status = RtlGetAce(Acl, 4, (PVOID)&Ace);
1217  ASSERT(NT_SUCCESS(Status));
1219  Status = RtlGetAce(Acl, 5, (PVOID)&Ace);
1220  ASSERT(NT_SUCCESS(Status));
1222  Status = RtlGetAce(Acl, 6, (PVOID)&Ace);
1223  ASSERT(NT_SUCCESS(Status));
1225 
1226  /* Now set this as the DACL for the liberal SD */
1227  Status = RtlSetDaclSecurityDescriptor(SmpLiberalSecurityDescriptor,
1228  TRUE,
1229  Acl,
1230  FALSE);
1231  ASSERT(NT_SUCCESS(Status));
1232 
1233 Quickie:
1234  /* Cleanup the SIDs */
1235  if (OwnerSid) RtlFreeHeap(RtlGetProcessHeap(), 0, OwnerSid);
1236  if (AdminSid) RtlFreeHeap(RtlGetProcessHeap(), 0, AdminSid);
1237  if (WorldSid) RtlFreeHeap(RtlGetProcessHeap(), 0, WorldSid);
1238  if (SystemSid) RtlFreeHeap(RtlGetProcessHeap(), 0, SystemSid);
1239  if (RestrictedSid) RtlFreeHeap(RtlGetProcessHeap(), 0, RestrictedSid);
1240  return Status;
1241 }
1242 
1243 NTSTATUS
1244 NTAPI
1246 {
1247  NTSTATUS Status;
1249  SECURITY_DESCRIPTOR_CONTROL OldFlag = 0;
1252  HANDLE DirHandle;
1253  PLIST_ENTRY NextEntry, Head;
1254 
1255  /* Open the GLOBAL?? directory */
1256  RtlInitUnicodeString(&DestinationString, L"\\??");
1257  InitializeObjectAttributes(&ObjectAttributes,
1258  &DestinationString,
1260  NULL,
1261  NULL);
1264  &ObjectAttributes);
1265  if (!NT_SUCCESS(Status))
1266  {
1267  DPRINT1("SMSS: Unable to open %wZ directory - Status == %lx\n",
1268  &DestinationString, Status);
1269  return Status;
1270  }
1271 
1272  /* Loop the DOS devices */
1273  Head = &SmpDosDevicesList;
1274  while (!IsListEmpty(Head))
1275  {
1276  /* Get the entry and remove it */
1277  NextEntry = RemoveHeadList(Head);
1278  RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
1279 
1280  /* Initialize the attributes, and see which descriptor is being used */
1281  InitializeObjectAttributes(&ObjectAttributes,
1282  &RegEntry->Name,
1285  SmpPrimarySecurityDescriptor);
1286  if (SmpPrimarySecurityDescriptor)
1287  {
1288  /* Save the old flag and set it while we create this link */
1289  OldFlag = SmpPrimarySecurityDescriptor->Control;
1290  SmpPrimarySecurityDescriptor->Control |= SE_DACL_DEFAULTED;
1291  }
1292 
1293  /* Create the symbolic link */
1294  DPRINT("Creating symlink for %wZ to %wZ\n", &RegEntry->Name, &RegEntry->Value);
1295  Status = NtCreateSymbolicLinkObject(&DirHandle,
1297  &ObjectAttributes,
1298  &RegEntry->Value);
1299  if (Status == STATUS_OBJECT_NAME_EXISTS)
1300  {
1301  /* Make it temporary and get rid of the handle */
1302  NtMakeTemporaryObject(DirHandle);
1303  NtClose(DirHandle);
1304 
1305  /* Treat this as success, and see if we got a name back */
1306  Status = STATUS_SUCCESS;
1307  if (RegEntry->Value.Length)
1308  {
1309  /* Create it now with this name */
1310  ObjectAttributes.Attributes &= ~OBJ_OPENIF;
1311  Status = NtCreateSymbolicLinkObject(&DirHandle,
1313  &ObjectAttributes,
1314  &RegEntry->Value);
1315  }
1316  }
1317 
1318  /* If we were using a security descriptor, restore the non-defaulted flag */
1319  if (ObjectAttributes.SecurityDescriptor)
1320  {
1321  SmpPrimarySecurityDescriptor->Control = OldFlag;
1322  }
1323 
1324  /* Print a failure if we failed to create the symbolic link */
1325  if (!NT_SUCCESS(Status))
1326  {
1327  DPRINT1("SMSS: Unable to create %wZ => %wZ symbolic link object - Status == 0x%lx\n",
1328  &RegEntry->Name,
1329  &RegEntry->Value,
1330  Status);
1331  break;
1332  }
1333 
1334  /* Close the handle */
1335  NtClose(DirHandle);
1336 
1337  /* Free this entry */
1338  if (RegEntry->AnsiValue) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue);
1339  if (RegEntry->Value.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer);
1340  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry);
1341  }
1342 
1343  /* Return the status */
1344  return Status;
1345 }
1346 
1347 VOID
1348 NTAPI
1350  IN PCHAR ImportName)
1351 {
1352  ULONG Length = 0, Chars;
1354  PWCHAR DllName, DllValue;
1355  ANSI_STRING ImportString;
1356  UNICODE_STRING ImportUnicodeString;
1357  NTSTATUS Status;
1358 
1359  /* Skip NTDLL since it's already always mapped */
1360  if (!_stricmp(ImportName, "ntdll.dll")) return;
1361 
1362  /* Initialize our strings */
1363  RtlInitAnsiString(&ImportString, ImportName);
1364  RtlInitEmptyUnicodeString(&ImportUnicodeString, Buffer, sizeof(Buffer));
1365  Status = RtlAnsiStringToUnicodeString(&ImportUnicodeString, &ImportString, FALSE);
1366  if (!NT_SUCCESS(Status)) return;
1367 
1368  /* Loop in case we find a forwarder */
1369  ImportUnicodeString.MaximumLength = ImportUnicodeString.Length + sizeof(UNICODE_NULL);
1370  while (Length < ImportUnicodeString.Length)
1371  {
1372  if (ImportUnicodeString.Buffer[Length / sizeof(WCHAR)] == L'.') break;
1373  Length += sizeof(WCHAR);
1374  }
1375 
1376  /* Break up the values as needed */
1377  DllValue = ImportUnicodeString.Buffer;
1378  DllName = &ImportUnicodeString.Buffer[ImportUnicodeString.MaximumLength / sizeof(WCHAR)];
1379  Chars = Length >> 1;
1380  wcsncpy(DllName, ImportUnicodeString.Buffer, Chars);
1381  DllName[Chars] = 0;
1382 
1383  /* Add the DLL to the list */
1384  SmpSaveRegistryValue(&SmpKnownDllsList, DllName, DllValue, TRUE);
1385 }
1386 
1387 NTSTATUS
1388 NTAPI
1391 {
1392  HANDLE DirFileHandle, DirHandle, SectionHandle, FileHandle, LinkHandle;
1395  NTSTATUS Status, Status1;
1396  PLIST_ENTRY NextEntry;
1398  ULONG_PTR ErrorParameters[3];
1399  UNICODE_STRING ErrorResponse;
1401  SECURITY_DESCRIPTOR_CONTROL OldFlag = 0;
1402  USHORT ImageCharacteristics;
1403 
1404  /* Initialize to NULL */
1405  DirFileHandle = NULL;
1406  DirHandle = NULL;
1407  NtPath.Buffer = NULL;
1408 
1409  /* Create the \KnownDLLs directory */
1410  InitializeObjectAttributes(&ObjectAttributes,
1411  Directory,
1413  NULL,
1414  SmpKnownDllsSecurityDescriptor);
1415  Status = NtCreateDirectoryObject(&DirHandle,
1417  &ObjectAttributes);
1418  if (!NT_SUCCESS(Status))
1419  {
1420  /* Handle failure */
1421  DPRINT1("SMSS: Unable to create %wZ directory - Status == %lx\n",
1422  Directory, Status);
1423  return Status;
1424  }
1425 
1426  /* Convert the path to native format */
1427  if (!RtlDosPathNameToNtPathName_U(Path->Buffer, &NtPath, NULL, NULL))
1428  {
1429  /* Fail if this didn't work */
1430  DPRINT1("SMSS: Unable to to convert %wZ to an Nt path\n", Path);
1431  Status = STATUS_OBJECT_NAME_INVALID;
1432  goto Quickie;
1433  }
1434 
1435  /* Open the path that was specified, which should be a directory */
1436  InitializeObjectAttributes(&ObjectAttributes,
1437  &NtPath,
1439  NULL,
1440  NULL);
1441  Status = NtOpenFile(&DirFileHandle,
1443  &ObjectAttributes,
1444  &IoStatusBlock,
1447  if (!NT_SUCCESS(Status))
1448  {
1449  /* Fail if we couldn't open it */
1450  DPRINT1("SMSS: Unable to open a handle to the KnownDll directory (%wZ)"
1451  "- Status == %lx\n",
1452  Path,
1453  Status);
1454  FileHandle = NULL;
1455  goto Quickie;
1456  }
1457 
1458  /* Temporarily hack the SD to use a default DACL for this symbolic link */
1459  if (SmpPrimarySecurityDescriptor)
1460  {
1461  OldFlag = SmpPrimarySecurityDescriptor->Control;
1462  SmpPrimarySecurityDescriptor->Control |= SE_DACL_DEFAULTED;
1463  }
1464 
1465  /* Create a symbolic link to the directory in the object manager */
1466  RtlInitUnicodeString(&DestinationString, L"KnownDllPath");
1467  InitializeObjectAttributes(&ObjectAttributes,
1468  &DestinationString,
1470  DirHandle,
1471  SmpPrimarySecurityDescriptor);
1472  Status = NtCreateSymbolicLinkObject(&LinkHandle,
1474  &ObjectAttributes,
1475  Path);
1476 
1477  /* Undo the hack */
1478  if (SmpPrimarySecurityDescriptor) SmpPrimarySecurityDescriptor->Control = OldFlag;
1479 
1480  /* Check if the symlink was created */
1481  if (!NT_SUCCESS(Status))
1482  {
1483  /* It wasn't, so bail out since the OS needs it to exist */
1484  DPRINT1("SMSS: Unable to create %wZ symbolic link - Status == %lx\n",
1485  &DestinationString, Status);
1486  LinkHandle = NULL;
1487  goto Quickie;
1488  }
1489 
1490  /* We created it permanent, we can go ahead and close the handle now */
1491  Status1 = NtClose(LinkHandle);
1492  ASSERT(NT_SUCCESS(Status1));
1493 
1494  /* Now loop the known DLLs */
1495  NextEntry = SmpKnownDllsList.Flink;
1496  while (NextEntry != &SmpKnownDllsList)
1497  {
1498  /* Get the entry and move on */
1499  RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
1500  NextEntry = NextEntry->Flink;
1501 
1502  DPRINT("Processing known DLL: %wZ-%wZ\n", &RegEntry->Name, &RegEntry->Value);
1503 
1504  /* Skip the entry if it's in the excluded list */
1505  if ((SmpFindRegistryValue(&SmpExcludeKnownDllsList,
1506  RegEntry->Name.Buffer)) ||
1507  (SmpFindRegistryValue(&SmpExcludeKnownDllsList,
1508  RegEntry->Value.Buffer)))
1509  {
1510  continue;
1511  }
1512 
1513  /* Open the actual file */
1514  InitializeObjectAttributes(&ObjectAttributes,
1515  &RegEntry->Value,
1517  DirFileHandle,
1518  NULL);
1519  Status1 = NtOpenFile(&FileHandle,
1521  &ObjectAttributes,
1522  &IoStatusBlock,
1526  /* If we failed, skip it */
1527  if (!NT_SUCCESS(Status1)) continue;
1528 
1529  /* Checksum it */
1530  Status = LdrVerifyImageMatchesChecksum((HANDLE)((ULONG_PTR)FileHandle | 1),
1532  RegEntry,
1533  &ImageCharacteristics);
1534  if (!NT_SUCCESS(Status))
1535  {
1536  /* Checksum failed, so don't even try going further -- kill SMSS */
1537  RtlInitUnicodeString(&ErrorResponse,
1538  L"Verification of a KnownDLL failed.");
1539  ErrorParameters[0] = (ULONG_PTR)&ErrorResponse;
1540  ErrorParameters[1] = Status;
1541  ErrorParameters[2] = (ULONG_PTR)&RegEntry->Value;
1542  SmpTerminate(ErrorParameters, 5, RTL_NUMBER_OF(ErrorParameters));
1543  }
1544  else if (!(ImageCharacteristics & IMAGE_FILE_DLL))
1545  {
1546  /* An invalid known DLL entry will also kill SMSS */
1547  RtlInitUnicodeString(&ErrorResponse,
1548  L"Non-DLL file included in KnownDLL list.");
1549  ErrorParameters[0] = (ULONG_PTR)&ErrorResponse;
1550  ErrorParameters[1] = STATUS_INVALID_IMPORT_OF_NON_DLL;
1551  ErrorParameters[2] = (ULONG_PTR)&RegEntry->Value;
1552  SmpTerminate(ErrorParameters, 5, RTL_NUMBER_OF(ErrorParameters));
1553  }
1554 
1555  /* Temporarily hack the SD to use a default DACL for this section */
1556  if (SmpLiberalSecurityDescriptor)
1557  {
1558  OldFlag = SmpLiberalSecurityDescriptor->Control;
1559  SmpLiberalSecurityDescriptor->Control |= SE_DACL_DEFAULTED;
1560  }
1561 
1562  /* Create the section for this known DLL */
1563  InitializeObjectAttributes(&ObjectAttributes,
1564  &RegEntry->Value,
1565  OBJ_PERMANENT,
1566  DirHandle,
1567  SmpLiberalSecurityDescriptor)
1568  Status = NtCreateSection(&SectionHandle,
1570  &ObjectAttributes,
1571  0,
1572  PAGE_EXECUTE,
1573  SEC_IMAGE,
1574  FileHandle);
1575 
1576  /* Undo the hack */
1577  if (SmpLiberalSecurityDescriptor) SmpLiberalSecurityDescriptor->Control = OldFlag;
1578 
1579  /* Check if we created the section okay */
1580  if (NT_SUCCESS(Status))
1581  {
1582  /* We can close it now, since it's marked permanent */
1583  Status1 = NtClose(SectionHandle);
1584  ASSERT(NT_SUCCESS(Status1));
1585  }
1586  else
1587  {
1588  /* If we couldn't make it "known", that's fine and keep going */
1589  DPRINT1("SMSS: CreateSection for KnownDll %wZ failed - Status == %lx\n",
1590  &RegEntry->Value, Status);
1591  }
1592 
1593  /* Close the file since we can move on to the next one */
1594  Status1 = NtClose(FileHandle);
1595  ASSERT(NT_SUCCESS(Status1));
1596  }
1597 
1598 Quickie:
1599  /* Close both handles and free the NT path buffer */
1600  if (DirHandle)
1601  {
1602  Status1 = NtClose(DirHandle);
1603  ASSERT(NT_SUCCESS(Status1));
1604  }
1605  if (DirFileHandle)
1606  {
1607  Status1 = NtClose(DirFileHandle);
1608  ASSERT(NT_SUCCESS(Status1));
1609  }
1610  if (NtPath.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, NtPath.Buffer);
1611  return Status;
1612 }
1613 
1614 NTSTATUS
1615 NTAPI
1617 {
1618  NTSTATUS Status;
1621  PLIST_ENTRY Head, NextEntry;
1622 
1623  /* Call the internal function */
1624  RtlInitUnicodeString(&DestinationString, L"\\KnownDlls");
1625  Status = SmpInitializeKnownDllsInternal(&DestinationString, &SmpKnownDllPath);
1626 
1627  /* Wipe out the list regardless of success */
1628  Head = &SmpKnownDllsList;
1629  while (!IsListEmpty(Head))
1630  {
1631  /* Remove this entry */
1632  NextEntry = RemoveHeadList(Head);
1633 
1634  /* Free it */
1635  RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
1636  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue);
1637  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer);
1638  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry);
1639  }
1640 
1641  /* All done */
1642  return Status;
1643 }
1644 
1645 NTSTATUS
1646 NTAPI
1648 {
1649  NTSTATUS Status;
1650  SYSTEM_BASIC_INFORMATION BasicInfo;
1651  SYSTEM_PROCESSOR_INFORMATION ProcessorInfo;
1654  HANDLE KeyHandle, KeyHandle2;
1656  PWCHAR ValueData;
1657  WCHAR ValueBuffer[512], ValueBuffer2[512];
1658  PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)ValueBuffer;
1659  PKEY_VALUE_PARTIAL_INFORMATION PartialInfo2 = (PVOID)ValueBuffer2;
1660 
1661  /* Get system basic information -- we'll need the CPU count */
1663  &BasicInfo,
1664  sizeof(BasicInfo),
1665  NULL);
1666  if (!NT_SUCCESS(Status))
1667  {
1668  /* Bail out on failure */
1669  DPRINT1("SMSS: Unable to query system basic information - %x\n", Status);
1670  return Status;
1671  }
1672 
1673  /* Get the processor information, we'll query a bunch of revision info */
1675  &ProcessorInfo,
1676  sizeof(ProcessorInfo),
1677  NULL);
1678  if (!NT_SUCCESS(Status))
1679  {
1680  /* Bail out on failure */
1681  DPRINT1("SMSS: Unable to query system processor information - %x\n", Status);
1682  return Status;
1683  }
1684 
1685  /* We'll be writing all these environment variables over here */
1686  RtlInitUnicodeString(&DestinationString,
1687  L"\\Registry\\Machine\\System\\CurrentControlSet\\"
1688  L"Control\\Session Manager\\Environment");
1689  InitializeObjectAttributes(&ObjectAttributes,
1690  &DestinationString,
1692  NULL,
1693  NULL);
1694  Status = NtOpenKey(&KeyHandle, GENERIC_WRITE, &ObjectAttributes);
1695  if (!NT_SUCCESS(Status))
1696  {
1697  /* Bail out on failure */
1698  DPRINT1("SMSS: Unable to open %wZ - %x\n", &DestinationString, Status);
1699  return Status;
1700  }
1701 
1702  /* First let's write the OS variable */
1703  RtlInitUnicodeString(&ValueName, L"OS");
1704  ValueData = L"Windows_NT";
1705  DPRINT("Setting %wZ to %S\n", &ValueName, ValueData);
1706  Status = NtSetValueKey(KeyHandle,
1707  &ValueName,
1708  0,
1709  REG_SZ,
1710  ValueData,
1711  (wcslen(ValueData) + 1) * sizeof(WCHAR));
1712  if (!NT_SUCCESS(Status))
1713  {
1714  DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n",
1715  &ValueName, Status);
1716  NtClose(KeyHandle);
1717  return Status;
1718  }
1719 
1720  /* Next, let's write the CPU architecture variable */
1721  RtlInitUnicodeString(&ValueName, L"PROCESSOR_ARCHITECTURE");
1722  switch (ProcessorInfo.ProcessorArchitecture)
1723  {
1724  /* Pick the correct string that matches the architecture */
1726  ValueData = L"x86";
1727  break;
1728 
1730  ValueData = L"AMD64";
1731  break;
1732 
1734  ValueData = L"IA64";
1735  break;
1736 
1737  default:
1738  ValueData = L"Unknown";
1739  break;
1740  }
1741 
1742  /* Set it */
1743  DPRINT("Setting %wZ to %S\n", &ValueName, ValueData);
1744  Status = NtSetValueKey(KeyHandle,
1745  &ValueName,
1746  0,
1747  REG_SZ,
1748  ValueData,
1749  (wcslen(ValueData) + 1) * sizeof(WCHAR));
1750  if (!NT_SUCCESS(Status))
1751  {
1752  DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n",
1753  &ValueName, Status);
1754  NtClose(KeyHandle);
1755  return Status;
1756  }
1757 
1758  /* And now let's write the processor level */
1759  RtlInitUnicodeString(&ValueName, L"PROCESSOR_LEVEL");
1760  swprintf(ValueBuffer, L"%u", ProcessorInfo.ProcessorLevel);
1761  DPRINT("Setting %wZ to %S\n", &ValueName, ValueBuffer);
1762  Status = NtSetValueKey(KeyHandle,
1763  &ValueName,
1764  0,
1765  REG_SZ,
1766  ValueBuffer,
1767  (wcslen(ValueBuffer) + 1) * sizeof(WCHAR));
1768  if (!NT_SUCCESS(Status))
1769  {
1770  DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n",
1771  &ValueName, Status);
1772  NtClose(KeyHandle);
1773  return Status;
1774  }
1775 
1776  /* Now open the hardware CPU key */
1777  RtlInitUnicodeString(&DestinationString,
1778  L"\\Registry\\Machine\\Hardware\\Description\\System\\"
1779  L"CentralProcessor\\0");
1780  InitializeObjectAttributes(&ObjectAttributes,
1781  &DestinationString,
1783  NULL,
1784  NULL);
1785  Status = NtOpenKey(&KeyHandle2, KEY_READ, &ObjectAttributes);
1786  if (!NT_SUCCESS(Status))
1787  {
1788  DPRINT1("SMSS: Unable to open %wZ - %x\n", &DestinationString, Status);
1789  NtClose(KeyHandle);
1790  return Status;
1791  }
1792 
1793  /* So that we can read the identifier out of it... */
1794  RtlInitUnicodeString(&ValueName, L"Identifier");
1795  Status = NtQueryValueKey(KeyHandle2,
1796  &ValueName,
1798  PartialInfo,
1799  sizeof(ValueBuffer),
1800  &ResultLength);
1801  if (!NT_SUCCESS(Status))
1802  {
1803  NtClose(KeyHandle2);
1804  NtClose(KeyHandle);
1805  DPRINT1("SMSS: Unable to read %wZ\\%wZ - %x\n",
1806  &DestinationString, &ValueName, Status);
1807  return Status;
1808  }
1809 
1810  /* As well as the vendor... */
1811  RtlInitUnicodeString(&ValueName, L"VendorIdentifier");
1812  Status = NtQueryValueKey(KeyHandle2,
1813  &ValueName,
1815  PartialInfo2,
1816  sizeof(ValueBuffer2),
1817  &ResultLength);
1818  NtClose(KeyHandle2);
1819  if (NT_SUCCESS(Status))
1820  {
1821  /* To combine it into a single string */
1822  swprintf((PWCHAR)PartialInfo->Data + wcslen((PWCHAR)PartialInfo->Data),
1823  L", %S",
1824  PartialInfo2->Data);
1825  }
1826 
1827  /* So that we can set this as the PROCESSOR_IDENTIFIER variable */
1828  RtlInitUnicodeString(&ValueName, L"PROCESSOR_IDENTIFIER");
1829  DPRINT("Setting %wZ to %s\n", &ValueName, PartialInfo->Data);
1830  Status = NtSetValueKey(KeyHandle,
1831  &ValueName,
1832  0,
1833  REG_SZ,
1834  PartialInfo->Data,
1835  (wcslen((PWCHAR)PartialInfo->Data) + 1) * sizeof(WCHAR));
1836  if (!NT_SUCCESS(Status))
1837  {
1838  DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n",
1839  &ValueName, Status);
1840  NtClose(KeyHandle);
1841  return Status;
1842  }
1843 
1844  /* Now let's get the processor architecture */
1845  RtlInitUnicodeString(&ValueName, L"PROCESSOR_REVISION");
1846  switch (ProcessorInfo.ProcessorArchitecture)
1847  {
1848  /* Check if this is an older Intel CPU */
1850  if ((ProcessorInfo.ProcessorRevision >> 8) == 0xFF)
1851  {
1852  /* These guys used a revision + stepping, so get the rev only */
1853  swprintf(ValueBuffer, L"%02x", ProcessorInfo.ProcessorRevision & 0xFF);
1854  _wcsupr(ValueBuffer);
1855  break;
1856  }
1857 
1858  /* Modern Intel, as well as 64-bit CPUs use a revision without stepping */
1861  swprintf(ValueBuffer, L"%04x", ProcessorInfo.ProcessorRevision);
1862  break;
1863 
1864  /* And anything else we'll just read the whole revision identifier */
1865  default:
1866  swprintf(ValueBuffer, L"%u", ProcessorInfo.ProcessorRevision);
1867  break;
1868  }
1869 
1870  /* Write the revision to the registry */
1871  DPRINT("Setting %wZ to %S\n", &ValueName, ValueBuffer);
1872  Status = NtSetValueKey(KeyHandle,
1873  &ValueName,
1874  0,
1875  REG_SZ,
1876  ValueBuffer,
1877  (wcslen(ValueBuffer) + 1) * sizeof(WCHAR));
1878  if (!NT_SUCCESS(Status))
1879  {
1880  DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n",
1881  &ValueName, Status);
1882  NtClose(KeyHandle);
1883  return Status;
1884  }
1885 
1886  /* And finally, write the number of CPUs */
1887  RtlInitUnicodeString(&ValueName, L"NUMBER_OF_PROCESSORS");
1888  swprintf(ValueBuffer, L"%d", BasicInfo.NumberOfProcessors);
1889  DPRINT("Setting %wZ to %S\n", &ValueName, ValueBuffer);
1890  Status = NtSetValueKey(KeyHandle,
1891  &ValueName,
1892  0,
1893  REG_SZ,
1894  ValueBuffer,
1895  (wcslen(ValueBuffer) + 1) * sizeof(WCHAR));
1896  if (!NT_SUCCESS(Status))
1897  {
1898  DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n",
1899  &ValueName, Status);
1900  NtClose(KeyHandle);
1901  return Status;
1902  }
1903 
1904  /* Now we need to write the safeboot option key in a different format */
1905  RtlInitUnicodeString(&DestinationString,
1906  L"\\Registry\\Machine\\System\\CurrentControlSet\\"
1907  L"Control\\Safeboot\\Option");
1908  InitializeObjectAttributes(&ObjectAttributes,
1909  &DestinationString,
1911  NULL,
1912  NULL);
1913  Status = NtOpenKey(&KeyHandle2, KEY_ALL_ACCESS, &ObjectAttributes);
1914  if (NT_SUCCESS(Status))
1915  {
1916  /* This was indeed a safeboot, so check what kind of safeboot it was */
1917  RtlInitUnicodeString(&ValueName, L"OptionValue");
1918  Status = NtQueryValueKey(KeyHandle2,
1919  &ValueName,
1921  PartialInfo,
1922  sizeof(ValueBuffer),
1923  &ResultLength);
1924  NtClose(KeyHandle2);
1925  if (NT_SUCCESS(Status))
1926  {
1927  /* Convert from the integer value to the correct specifier */
1928  RtlInitUnicodeString(&ValueName, L"SAFEBOOT_OPTION");
1929  switch (*(PULONG)PartialInfo->Data)
1930  {
1931  case 1:
1932  wcscpy(ValueBuffer, L"MINIMAL");
1933  break;
1934  case 2:
1935  wcscpy(ValueBuffer, L"NETWORK");
1936  break;
1937  case 3:
1938  wcscpy(ValueBuffer, L"DSREPAIR");
1939  break;
1940  }
1941 
1942  /* And write it in the environment! */
1943  DPRINT("Setting %wZ to %S\n", &ValueName, ValueBuffer);
1944  Status = NtSetValueKey(KeyHandle,
1945  &ValueName,
1946  0,
1947  REG_SZ,
1948  ValueBuffer,
1949  (wcslen(ValueBuffer) + 1) * sizeof(WCHAR));
1950  if (!NT_SUCCESS(Status))
1951  {
1952  DPRINT1("SMSS: Failed writing %wZ environment variable - %x\n",
1953  &ValueName, Status);
1954  NtClose(KeyHandle);
1955  return Status;
1956  }
1957  }
1958  else
1959  {
1960  DPRINT1("SMSS: Failed querying safeboot option = %x\n", Status);
1961  }
1962  }
1963 
1964  /* We are all done now */
1965  NtClose(KeyHandle);
1966  return STATUS_SUCCESS;
1967 }
1968 
1969 NTSTATUS
1970 NTAPI
1972 {
1973  BOOLEAN OldState, HavePrivilege = FALSE;
1974  NTSTATUS Status;
1975  HANDLE FileHandle, OtherFileHandle;
1979  UNICODE_STRING FileString;
1980  FILE_BASIC_INFORMATION BasicInfo;
1981  FILE_DISPOSITION_INFORMATION DeleteInformation;
1983  PLIST_ENTRY Head, NextEntry;
1985  PWCHAR FileName;
1987 
1988  /* Give us access to restore any files we want */
1989  Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &OldState);
1990  if (NT_SUCCESS(Status)) HavePrivilege = TRUE;
1991 
1992  // FIXME: Handle SFC-protected file renames!
1994  DPRINT1("SMSS: FIXME: Handle SFC-protected file renames!\n");
1995 
1996  /* Process pending files to rename */
1997  Head = &SmpFileRenameList;
1998  while (!IsListEmpty(Head))
1999  {
2000  /* Get this entry */
2001  NextEntry = RemoveHeadList(Head);
2002  RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
2003  DPRINT("Processing PFRO: '%wZ' / '%wZ'\n", &RegEntry->Value, &RegEntry->Name);
2004 
2005  /* Skip past the '@' marker */
2006  if (!(RegEntry->Value.Length) && (*RegEntry->Name.Buffer == L'@'))
2007  {
2008  RegEntry->Name.Length -= sizeof(UNICODE_NULL);
2009  RegEntry->Name.Buffer++;
2010  }
2011 
2012  /* Open the file for delete access */
2013  InitializeObjectAttributes(&ObjectAttributes,
2014  &RegEntry->Name,
2016  NULL,
2017  NULL);
2018  Status = NtOpenFile(&OtherFileHandle,
2019  DELETE | SYNCHRONIZE,
2020  &ObjectAttributes,
2021  &IoStatusBlock,
2024  if (!NT_SUCCESS(Status)) goto Quickie;
2025 
2026  /* Check if it's a rename or just a delete */
2027  ValueLength = RegEntry->Value.Length;
2028  if (!ValueLength)
2029  {
2030  /* Just a delete, set up the class, length and buffer */
2031  InformationClass = FileDispositionInformation;
2032  Length = sizeof(DeleteInformation);
2033  Buffer = (PFILE_RENAME_INFORMATION)&DeleteInformation;
2034 
2035  /* Set the delete disposition */
2036  DeleteInformation.DeleteFile = TRUE;
2037  }
2038  else
2039  {
2040  /* This is a rename, setup the class and length */
2041  InformationClass = FileRenameInformation;
2042  Length = ValueLength + sizeof(FILE_RENAME_INFORMATION);
2043 
2044  /* Skip past the special markers */
2045  FileName = RegEntry->Value.Buffer;
2046  if ((*FileName == L'!') || (*FileName == L'@'))
2047  {
2048  FileName++;
2049  Length -= sizeof(UNICODE_NULL);
2050  }
2051 
2052  /* Now allocate the buffer for the rename information */
2053  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), SmBaseTag, Length);
2054  if (Buffer)
2055  {
2056  /* Setup the buffer to point to the filename, and copy it */
2057  Buffer->RootDirectory = NULL;
2058  Buffer->FileNameLength = Length - sizeof(FILE_RENAME_INFORMATION);
2059  Buffer->ReplaceIfExists = FileName != RegEntry->Value.Buffer;
2060  RtlCopyMemory(Buffer->FileName, FileName, Buffer->FileNameLength);
2061  }
2062  else
2063  {
2064  /* Fail */
2065  Status = STATUS_NO_MEMORY;
2066  }
2067  }
2068 
2069  /* Check if everything is okay till here */
2070  if (NT_SUCCESS(Status))
2071  {
2072  /* Now either rename or delete the file as requested */
2073  Status = NtSetInformationFile(OtherFileHandle,
2074  &IoStatusBlock,
2075  Buffer,
2076  Length,
2077  InformationClass);
2078 
2079  /* Check if we seem to have failed because the file was readonly */
2080  if (!NT_SUCCESS(Status) &&
2081  (InformationClass == FileRenameInformation) &&
2082  (Status == STATUS_OBJECT_NAME_COLLISION) &&
2083  Buffer->ReplaceIfExists)
2084  {
2085  /* Open the file for write attribute access this time... */
2086  DPRINT("\nSMSS: '%wZ' => '%wZ' failed - Status == %x, Possible readonly target\n",
2087  &RegEntry->Name,
2088  &RegEntry->Value,
2090  FileString.Length = RegEntry->Value.Length - sizeof(WCHAR);
2091  FileString.MaximumLength = RegEntry->Value.MaximumLength - sizeof(WCHAR);
2092  FileString.Buffer = FileName;
2093  InitializeObjectAttributes(&ObjectAttributes,
2094  &FileString,
2096  NULL,
2097  NULL);
2098  Status = NtOpenFile(&FileHandle,
2100  &ObjectAttributes,
2101  &IoStatusBlock,
2104  if (!NT_SUCCESS(Status))
2105  {
2106  /* That didn't work, so bail out */
2107  DPRINT1(" SMSS: Open Existing file Failed - Status == %x\n",
2108  Status);
2109  }
2110  else
2111  {
2112  /* Now remove the read-only attribute from the file */
2113  DPRINT(" SMSS: Open Existing Success\n");
2114  RtlZeroMemory(&BasicInfo, sizeof(BasicInfo));
2116  Status = NtSetInformationFile(FileHandle,
2117  &IoStatusBlock,
2118  &BasicInfo,
2119  sizeof(BasicInfo),
2121  NtClose(FileHandle);
2122  if (!NT_SUCCESS(Status))
2123  {
2124  /* That didn't work, bail out */
2125  DPRINT1(" SMSS: Set To NORMAL Failed - Status == %x\n",
2126  Status);
2127  }
2128  else
2129  {
2130  /* Now that the file is no longer read-only, delete! */
2131  DPRINT(" SMSS: Set To NORMAL OK\n");
2132  Status = NtSetInformationFile(OtherFileHandle,
2133  &IoStatusBlock,
2134  Buffer,
2135  Length,
2137  if (!NT_SUCCESS(Status))
2138  {
2139  /* That failed too! */
2140  DPRINT1(" SMSS: Re-Rename Failed - Status == %x\n",
2141  Status);
2142  }
2143  else
2144  {
2145  /* Everything ok */
2146  DPRINT(" SMSS: Re-Rename Worked OK\n");
2147  }
2148  }
2149  }
2150  }
2151  }
2152 
2153  /* Close the file handle and check the operation result */
2154  NtClose(OtherFileHandle);
2155 Quickie:
2156  if (!NT_SUCCESS(Status))
2157  {
2158  /* We totally failed */
2159  DPRINT1("SMSS: '%wZ' => '%wZ' failed - Status == %x\n",
2160  &RegEntry->Name, &RegEntry->Value, Status);
2161  }
2162  else if (RegEntry->Value.Length)
2163  {
2164  /* We succeed with a rename */
2165  DPRINT("SMSS: '%wZ' (renamed to) '%wZ'\n", &RegEntry->Name, &RegEntry->Value);
2166  }
2167  else
2168  {
2169  /* We succeeded with a delete */
2170  DPRINT("SMSS: '%wZ' (deleted)\n", &RegEntry->Name);
2171  }
2172 
2173  /* Now free this entry and keep going */
2174  if (RegEntry->AnsiValue) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue);
2175  if (RegEntry->Value.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer);
2176  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry);
2177  }
2178 
2179  /* Put back the restore privilege if we had requested it, and return */
2180  if (HavePrivilege) RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, FALSE, FALSE, &OldState);
2181  return Status;
2182 }
2183 
2184 NTSTATUS
2185 NTAPI
2187 {
2188  NTSTATUS Status;
2189  PLIST_ENTRY Head, NextEntry;
2191  PVOID OriginalEnvironment;
2192  ULONG MuSessionId = 0;
2194  HANDLE KeyHandle;
2196 
2197  /* Initialize the keywords we'll be looking for */
2201 
2202  /* Initialize all the registry-associated list heads */
2203  InitializeListHead(&SmpBootExecuteList);
2204  InitializeListHead(&SmpSetupExecuteList);
2205  InitializeListHead(&SmpPagingFileList);
2206  InitializeListHead(&SmpDosDevicesList);
2207  InitializeListHead(&SmpFileRenameList);
2208  InitializeListHead(&SmpKnownDllsList);
2209  InitializeListHead(&SmpExcludeKnownDllsList);
2210  InitializeListHead(&SmpSubSystemList);
2211  InitializeListHead(&SmpSubSystemsToLoad);
2212  InitializeListHead(&SmpSubSystemsToDefer);
2213  InitializeListHead(&SmpExecuteList);
2215 
2216  /* Initialize the SMSS environment */
2218  if (!NT_SUCCESS(Status))
2219  {
2220  /* Fail if there was a problem */
2221  DPRINT1("SMSS: Unable to allocate default environment - Status == %X\n",
2222  Status);
2224  return Status;
2225  }
2226 
2227  /* Check if we were booted in PE mode (LiveCD should have this) */
2228  RtlInitUnicodeString(&DestinationString,
2229  L"\\Registry\\Machine\\System\\CurrentControlSet\\"
2230  L"Control\\MiniNT");
2231  InitializeObjectAttributes(&ObjectAttributes,
2232  &DestinationString,
2234  NULL,
2235  NULL);
2236  Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
2237  if (NT_SUCCESS(Status))
2238  {
2239  /* If the key exists, we were */
2240  NtClose(KeyHandle);
2241  MiniNTBoot = TRUE;
2242  }
2243 
2244  /* Print out if this is the case */
2245  if (MiniNTBoot) DPRINT("SMSS: !!! MiniNT Boot !!!\n");
2246 
2247  /* Open the environment key to see if we are booted in safe mode */
2248  RtlInitUnicodeString(&DestinationString,
2249  L"\\Registry\\Machine\\System\\CurrentControlSet\\"
2250  L"Control\\Session Manager\\Environment");
2251  InitializeObjectAttributes(&ObjectAttributes,
2252  &DestinationString,
2254  NULL,
2255  NULL);
2256  Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
2257  if (NT_SUCCESS(Status))
2258  {
2259  /* Delete the value if we found it */
2260  RtlInitUnicodeString(&DestinationString, L"SAFEBOOT_OPTION");
2261  NtDeleteValueKey(KeyHandle, &DestinationString);
2262  NtClose(KeyHandle);
2263  }
2264 
2265  /* Switch environments, then query the registry for all needed settings */
2266  OriginalEnvironment = NtCurrentPeb()->ProcessParameters->Environment;
2267  NtCurrentPeb()->ProcessParameters->Environment = SmpDefaultEnvironment;
2269  L"Session Manager",
2271  NULL,
2272  NULL);
2273  SmpDefaultEnvironment = NtCurrentPeb()->ProcessParameters->Environment;
2274  NtCurrentPeb()->ProcessParameters->Environment = OriginalEnvironment;
2275  if (!NT_SUCCESS(Status))
2276  {
2277  /* We failed somewhere in registry initialization, which is bad... */
2278  DPRINT1("SMSS: RtlQueryRegistryValues failed - Status == %lx\n", Status);
2280  return Status;
2281  }
2282 
2283  /* Now we can start acting on the registry settings. First to DOS devices */
2284  Status = SmpInitializeDosDevices();
2285  if (!NT_SUCCESS(Status))
2286  {
2287  /* Failed */
2288  DPRINT1("SMSS: Unable to initialize DosDevices configuration - Status == %lx\n",
2289  Status);
2291  return Status;
2292  }
2293 
2294  /* Next create the session directory... */
2295  RtlInitUnicodeString(&DestinationString, L"\\Sessions");
2296  InitializeObjectAttributes(&ObjectAttributes,
2297  &DestinationString,
2299  NULL,
2300  SmpPrimarySecurityDescriptor);
2303  &ObjectAttributes);
2304  if (!NT_SUCCESS(Status))
2305  {
2306  /* Fail */
2307  DPRINT1("SMSS: Unable to create %wZ object directory - Status == %lx\n",
2308  &DestinationString, Status);
2310  return Status;
2311  }
2312 
2313  /* Next loop all the boot execute binaries */
2314  Head = &SmpBootExecuteList;
2315  while (!IsListEmpty(Head))
2316  {
2317  /* Remove each one from the list */
2318  NextEntry = RemoveHeadList(Head);
2319 
2320  /* Execute it */
2321  RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
2322  SmpExecuteCommand(&RegEntry->Name, 0, NULL, 0);
2323 
2324  /* And free it */
2325  if (RegEntry->AnsiValue) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue);
2326  if (RegEntry->Value.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer);
2327  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry);
2328  }
2329 
2330  /* Now do any pending file rename operations... */
2332 
2333  /* And initialize known DLLs... */
2334  Status = SmpInitializeKnownDlls();
2335  if (!NT_SUCCESS(Status))
2336  {
2337  /* Fail if that didn't work */
2338  DPRINT1("SMSS: Unable to initialize KnownDll configuration - Status == %lx\n",
2339  Status);
2341  return Status;
2342  }
2343 
2344  /* Create the needed page files */
2345  if (!MiniNTBoot)
2346  {
2347  /* Loop every page file */
2348  Head = &SmpPagingFileList;
2349  while (!IsListEmpty(Head))
2350  {
2351  /* Remove each one from the list */
2352  NextEntry = RemoveHeadList(Head);
2353 
2354  /* Create the descriptor for it */
2355  RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
2356  SmpCreatePagingFileDescriptor(&RegEntry->Name);
2357 
2358  /* And free it */
2359  if (RegEntry->AnsiValue) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->AnsiValue);
2360  if (RegEntry->Value.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry->Value.Buffer);
2361  RtlFreeHeap(RtlGetProcessHeap(), 0, RegEntry);
2362  }
2363 
2364  /* Now create all the paging files for the descriptors that we have */
2366  }
2367 
2368  /* Tell Cm it's now safe to fully enable write access to the registry */
2370 
2371  /* Create all the system-based environment variables for later inheriting */
2373  if (!NT_SUCCESS(Status))
2374  {
2375  /* Handle failure */
2377  return Status;
2378  }
2379 
2380  /* And finally load all the subsystems for our first session! */
2381  Status = SmpLoadSubSystemsForMuSession(&MuSessionId,
2383  InitialCommand);
2384  ASSERT(MuSessionId == 0);
2386  return Status;
2387 }
2388 
2389 NTSTATUS
2390 NTAPI
2391 SmpInit(IN PUNICODE_STRING InitialCommand,
2393 {
2394  NTSTATUS Status, Status2;
2396  UNICODE_STRING PortName, EventName;
2397  HANDLE EventHandle, PortHandle;
2398  ULONG HardErrorMode;
2399 
2400  /* Create the SMSS Heap */
2401  SmBaseTag = RtlCreateTagHeap(RtlGetProcessHeap(),
2402  0,
2403  L"SMSS!",
2404  L"INIT");
2405  SmpHeap = RtlGetProcessHeap();
2406 
2407  /* Enable hard errors */
2408  HardErrorMode = TRUE;
2411  &HardErrorMode,
2412  sizeof(HardErrorMode));
2413 
2414  /* Initialize the subsystem list and the session list, plus their locks */
2419 
2420  /* Initialize the process list */
2421  InitializeListHead(&NativeProcessList);
2422 
2423  /* Initialize session parameters */
2424  SmpNextSessionId = 1;
2427 
2428  /* Create the initial security descriptors */
2430  if (!NT_SUCCESS(Status))
2431  {
2432  /* Fail */
2434  return Status;
2435  }
2436 
2437  /* Initialize subsystem names */
2438  RtlInitUnicodeString(&SmpSubsystemName, L"NT-Session Manager");
2439  RtlInitUnicodeString(&PosixName, L"POSIX");
2440  RtlInitUnicodeString(&Os2Name, L"OS2");
2441 
2442  /* Create the SM API Port */
2443  RtlInitUnicodeString(&PortName, L"\\SmApiPort");
2444  InitializeObjectAttributes(&ObjectAttributes, &PortName, 0, NULL, NULL);
2445  Status = NtCreatePort(&PortHandle,
2446  &ObjectAttributes,
2447  sizeof(SB_CONNECTION_INFO),
2448  sizeof(SM_API_MSG),
2449  sizeof(SB_API_MSG) * 32);
2450  ASSERT(NT_SUCCESS(Status));
2451  SmpDebugPort = PortHandle;
2452 
2453  /* Create two SM API threads */
2455  NULL,
2456  FALSE,
2457  0,
2458  0,
2459  0,
2460  SmpApiLoop,
2461  PortHandle,
2462  NULL,
2463  NULL);
2464  ASSERT(NT_SUCCESS(Status));
2466  NULL,
2467  FALSE,
2468  0,
2469  0,
2470  0,
2471  SmpApiLoop,
2472  PortHandle,
2473  NULL,
2474  NULL);
2475  ASSERT(NT_SUCCESS(Status));
2476 
2477  /* Create the write event that autochk can set after running */
2478  RtlInitUnicodeString(&EventName, L"\\Device\\VolumesSafeForWriteAccess");
2479  InitializeObjectAttributes(&ObjectAttributes,
2480  &EventName,
2481  OBJ_PERMANENT,
2482  NULL,
2483  NULL);
2484  Status2 = NtCreateEvent(&EventHandle,
2486  &ObjectAttributes,
2487  0,
2488  0);
2489  if (!NT_SUCCESS(Status2))
2490  {
2491  /* Should never really fail */
2492  DPRINT1("SMSS: Unable to create %wZ event - Status == %lx\n",
2493  &EventName, Status2);
2494  ASSERT(NT_SUCCESS(Status2));
2495  }
2496 
2497  /* Now initialize everything else based on the registry parameters */
2498  Status = SmpLoadDataFromRegistry(InitialCommand);
2499  if (NT_SUCCESS(Status))
2500  {
2501  /* Autochk should've run now. Set the event and save the CSRSS handle */
2502  *ProcessHandle = SmpWindowsSubSysProcess;
2503  NtSetEvent(EventHandle, 0);
2504  NtClose(EventHandle);
2505  }
2506 
2507  /* All done */
2508  return Status;
2509 }
HANDLE SmpDosDevicesObjectDirectory
Definition: sminit.c:26
#define CM_BOOT_FLAG_SMSS
Definition: cmtypes.h:151
DWORD *typedef PVOID
Definition: winlogon.h:61
IN CINT OUT PVOID IN ULONG OUT PULONG ResultLength
Definition: conport.c:47
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
signed char * PCHAR
Definition: retypes.h:7
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
LIST_ENTRY SmpBootExecuteList
Definition: sminit.c:19
_Must_inspect_result_ typedef _In_ PVOID Unused
Definition: iotypes.h:1128
PVOID SmpInitLastCall
Definition: sminit.c:33
#define IN
Definition: typedefs.h:38
#define GENERIC_ALL
Definition: nt_native.h:92
#define SECURITY_LOCAL_SYSTEM_RID
Definition: setypes.h:546
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
SECURITY_DESCRIPTOR SmpPrimarySDBody
Definition: sminit.c:35
*BytesInUnicodeString PWCH UnicodeString
Definition: rtlfuncs.h:1980
NTSTATUS NTAPI NtCreateSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection OPTIONAL, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL)
Definition: section.c:3372
#define SMSS_CHECKPOINT(x, y)
Definition: sminit.c:43
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4693
UNICODE_STRING PosixName
Definition: sminit.c:18
USHORT MaximumLength
Definition: env_spec_w32.h:370
NTSTATUS NTAPI SmpSaveRegistryValue(IN PLIST_ENTRY ListAddress, IN PWSTR Name, IN PWCHAR Value, IN BOOLEAN Flags)
Definition: sminit.c:54
PISECURITY_DESCRIPTOR SmpPrimarySecurityDescriptor
Definition: sminit.c:37
UNICODE_STRING SmpDefaultLibPath
Definition: sminit.c:28
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
NTSTATUS NTAPI SmpConfigureProtectionMode(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:219
static PSID AdminSid
Definition: msgina.c:39
#define KEY_READ
Definition: nt_native.h:1023
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
PISECURITY_DESCRIPTOR SmpApiPortSecurityDescriptor
Definition: sminit.c:38
NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: obdir.c:359
LIST_ENTRY SmpExcludeKnownDllsList
Definition: sminit.c:21
char CHAR
Definition: xmlstorage.h:175
#define RTL_QUERY_REGISTRY_TOPKEY
Definition: nt_native.h:129
_In_ PCWSTR _In_z_ PCWSTR _In_ ULONG ValueType
Definition: rtlfuncs.h:4000
SECURITY_DESCRIPTOR SmpKnownDllsSDBody
Definition: sminit.c:35
HANDLE SmpWindowsSubSysProcess
Definition: smsubsys.c:20
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
static SID_IDENTIFIER_AUTHORITY WorldAuthority
Definition: security.c:14
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
#define SE_RESTORE_PRIVILEGE
Definition: security.c:672
PVOID *typedef PWSTR
Definition: winlogon.h:66
NTSTATUS NTAPI SmpConfigureKnownDlls(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:459
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:100
ULONG NTAPI SmpApiLoop(IN PVOID Parameter)
Definition: smloop.c:335
#define RTL_QUERY_REGISTRY_NOEXPAND
Definition: nt_native.h:139
NTSTATUS NTAPI SmpConfigureEnvironment(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:482
#define OBJ_PERMANENT
Definition: winternl.h:226
NTSYSAPI NTSTATUS NTAPI RtlAdjustPrivilege(_In_ ULONG Privilege, _In_ BOOLEAN NewValue, _In_ BOOLEAN ForThread, _Out_ PBOOLEAN OldValue)
LIST_ENTRY SmpDosDevicesList
Definition: sminit.c:20
LIST_ENTRY SmpPagingFileList
Definition: sminit.c:19
NTSTATUS NTAPI NtMakeTemporaryObject(IN HANDLE ObjectHandle)
Definition: oblife.c:1385
NTSYSAPI NTSTATUS NTAPI RtlGetAce(PACL Acl, ULONG AceIndex, PVOID *Ace)
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
NTSTATUS NTAPI SmpInit(IN PUNICODE_STRING InitialCommand, OUT PHANDLE ProcessHandle)
Definition: sminit.c:2391
uint16_t * PWCHAR
Definition: typedefs.h:54
LIST_ENTRY NativeProcessList
Definition: sminit.c:22
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define RTL_REGISTRY_CONTROL
Definition: nt_native.h:163
#define InsertTailList(ListHead, Entry)
NTSTATUS NTAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PVOID Buffer, IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
Definition: obdir.c:456
#define WCHAR
Definition: msvc.h:43
NTSYSAPI NTSTATUS NTAPI RtlAllocateAndInitializeSid(IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthority0, IN ULONG SubAuthority1, IN ULONG SubAuthority2, IN ULONG SubAuthority3, IN ULONG SubAuthority4, IN ULONG SubAuthority5, IN ULONG SubAuthority6, IN ULONG SubAuthority7, OUT PSID *Sid)
Definition: sid.c:290
#define _stricmp
Definition: cat.c:22
#define SYMBOLIC_LINK_ALL_ACCESS
Definition: nt_native.h:1267
NTSTATUS NTAPI LdrVerifyImageMatchesChecksum(IN HANDLE FileHandle, IN PLDR_CALLBACK Callback, IN PVOID CallbackContext, OUT PUSHORT ImageCharacteristics)
Definition: ldrapi.c:837
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
NTSYSAPI NTSTATUS WINAPI RtlAddAccessAllowedAce(PACL, DWORD, DWORD, PSID)
#define IMAGE_FILE_DLL
Definition: pedump.c:169
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define FILE_SHARE_READ
Definition: compat.h:125
BOOLEAN RegPosixSingleInstance
Definition: smsubsys.c:22
NTSYSAPI NTSTATUS NTAPI RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision)
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define PROCESSOR_ARCHITECTURE_IA64
Definition: ketypes.h:111
UNICODE_STRING SmpASyncKeyword
Definition: smutil.c:34
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
VOID NTAPI SmpPagingFileInitialize(VOID)
Definition: pagefile.c:75
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292
#define OBJ_OPENIF
Definition: winternl.h:229
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
HANDLE FileHandle
Definition: stats.c:38
HANDLE SmpWindowsSubSysProcessId
Definition: smsubsys.c:21
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define RTL_QUERY_REGISTRY_DELETE
Definition: nt_native.h:153
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define ANSI_NULL
PWCHAR SmpDefaultEnvironment
Definition: sminit.c:27
PVOID SmpHeap
Definition: sminit.c:24
NTSTATUS NTAPI NtInitializeRegistry(IN USHORT Flag)
Definition: ntapi.c:1298
PISECURITY_DESCRIPTOR SmpLiberalSecurityDescriptor
Definition: sminit.c:37
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
WORD SECURITY_DESCRIPTOR_CONTROL
Definition: lsa.idl:37
NTSTATUS NTAPI SmpConfigureAllowProtectedRenames(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:246
#define REG_MULTI_SZ
Definition: nt_native.h:1501
PCHAR AnsiValue
Definition: smss.h:55
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSTATUS NTAPI SmpInitializeKnownDllPath(IN PUNICODE_STRING DllPath, IN PWCHAR Buffer, IN ULONG Length)
Definition: sminit.c:429
NTSTATUS NTAPI SmpConfigureExcludeKnownDlls(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:381
LIST_ENTRY SmpSubSystemsToLoad
Definition: sminit.c:21
Definition: card.h:12
ULONG NTAPI RtlCreateTagHeap(IN HANDLE HeapHandle, IN ULONG Flags, IN PWSTR TagName, IN PWSTR TagSubName)
Definition: heap.c:3875
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:3988
#define ACL_REVISION2
Definition: setypes.h:43
struct _ACL ACL
_Out_ _Inout_ POEM_STRING DestinationString
Definition: rtlfuncs.h:1869
smooth NULL
Definition: ftsmooth.c:416
#define RTL_QUERY_REGISTRY_SUBKEY
Definition: nt_native.h:125
struct _FILE_RENAME_INFORMATION FILE_RENAME_INFORMATION
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
NTSYSAPI NTSTATUS NTAPI RtlSetEnvironmentVariable(_In_z_ PWSTR *Environment, _In_ PUNICODE_STRING Name, _In_ PUNICODE_STRING Value)
#define PAGE_EXECUTE
Definition: nt_native.h:1306
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
_CRTIMP wchar_t *__cdecl _wcsupr(_Inout_z_ wchar_t *_String)
#define SECURITY_NT_AUTHORITY
Definition: setypes.h:526
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define SE_DACL_DEFAULTED
Definition: setypes.h:768
UNICODE_STRING SmpKnownDllPath
Definition: sminit.c:28
#define NtCurrentProcess()
Definition: nt_native.h:1657
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
NTSYSAPI NTSTATUS NTAPI NtDeleteValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName)
Definition: ntapi.c:994
LIST_ENTRY SmpSetupExecuteList
Definition: sminit.c:19
#define CONTAINER_INHERIT_ACE
Definition: setypes.h:715
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3952
unsigned char BOOLEAN
NTSYSAPI NTSTATUS NTAPI NtQueryValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS NTAPI SmpCreateDynamicEnvironmentVariables(VOID)
Definition: sminit.c:1647
ULONG SmpCalledConfigEnv
Definition: sminit.c:29
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI NtCreatePort(OUT PHANDLE PortHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG MaxConnectInfoLength, IN ULONG MaxDataLength, IN ULONG MaxPoolUsage)
Definition: create.c:212
#define SECURITY_BUILTIN_DOMAIN_RID
Definition: setypes.h:553
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:458
LIST_ENTRY List
Definition: psmgr.c:57
NTSTATUS NTAPI SmpProcessFileRenames(VOID)
Definition: sminit.c:1971
NTSTATUS SmpInitReturnStatus
Definition: sminit.c:32
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
VOID NTAPI SmpTranslateSystemPartitionInformation(VOID)
Definition: sminit.c:786
Registry entry.
Definition: regfs.h:30
#define SECURITY_WORLD_SID_AUTHORITY
Definition: setypes.h:499
ULONG SmBaseTag
Definition: sminit.c:25
#define MAX_PATH
Definition: compat.h:26
#define swprintf(buf, format,...)
Definition: sprintf.c:56
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
NTSTATUS NTAPI SmpConfigureFileRenames(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:350
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
LIST_ENTRY SmpFileRenameList
Definition: sminit.c:20
#define SECURITY_WORLD_RID
Definition: setypes.h:513
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3393
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
LIST_ENTRY Entry
Definition: smss.h:52
#define PROCESSOR_ARCHITECTURE_AMD64
Definition: ketypes.h:114
#define SECURITY_CREATOR_OWNER_RID
Definition: setypes.h:517
_In_ PUNICODE_STRING Name
Definition: mrx.h:218
UNICODE_STRING SmpDebugKeyword
Definition: smutil.c:34
struct _FILE_RENAME_INFORMATION * PFILE_RENAME_INFORMATION
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
HANDLE SmpDebugPort
Definition: sminit.c:26
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
PISECURITY_DESCRIPTOR SmpKnownDllsSecurityDescriptor
Definition: sminit.c:38
_Out_ _Inout_ POEM_STRING _In_ PCUNICODE_STRING SourceString
Definition: rtlfuncs.h:1869
UNICODE_STRING Name
Definition: smss.h:53
static const WCHAR L[]
Definition: oid.c:1087
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
VOID UINTN Length
Definition: acefiex.h:744
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
#define FILE_EXECUTE
Definition: nt_native.h:642
NTSTATUS NTAPI SmpCreatePagingFiles(VOID)
Definition: pagefile.c:998
PSID WorldSid
Definition: globals.c:15
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define GENERIC_READ
Definition: compat.h:124
Definition: typedefs.h:117
NTSYSAPI NTSTATUS NTAPI RtlCreateUserThread(_In_ PVOID ThreadContext, _Out_ HANDLE *OutThreadHandle, _Reserved_ PVOID Reserved1, _Reserved_ PVOID Reserved2, _Reserved_ PVOID Reserved3, _Reserved_ PVOID Reserved4, _Reserved_ PVOID Reserved5, _Reserved_ PVOID Reserved6, _Reserved_ PVOID Reserved7, _Reserved_ PVOID Reserved8)
#define SYNCHRONIZE
Definition: nt_native.h:61
LIST_ENTRY SmpSessionListHead
Definition: smsessn.c:27
NTSTATUS NTAPI SmpLoadSubSystemsForMuSession(IN PULONG MuSessionId, OUT PHANDLE ProcessId, IN PUNICODE_STRING InitialCommand)
Definition: smsubsys.c:513
UINTN UINT8 Value
Definition: acefiex.h:751
NTSTATUS NTAPI SmpExecuteCommand(IN PUNICODE_STRING CommandLine, IN ULONG MuSessionId, OUT PHANDLE ProcessId, IN ULONG Flags)
Definition: smss.c:221
NTSTATUS NTAPI SmpInitializeKnownDllsInternal(IN PUNICODE_STRING Directory, IN PUNICODE_STRING Path)
Definition: sminit.c:1389
LIST_ENTRY SmpExecuteList
Definition: sminit.c:22
RTL_CRITICAL_SECTION SmpSessionListLock
Definition: smsessn.c:26
struct _OBJECT_DIRECTORY_INFORMATION OBJECT_DIRECTORY_INFORMATION
Status
Definition: gdiplustypes.h:24
NTSYSAPI NTSTATUS NTAPI RtlCreateEnvironment(_In_ BOOLEAN Inherit, _Out_ PWSTR *Environment)
#define PROCESSOR_ARCHITECTURE_INTEL
Definition: ketypes.h:105
NTSTATUS NTAPI SmpConfigureMemoryMgmt(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:337
BOOLEAN SmpDbgSsLoaded
Definition: smsessn.c:30
struct _FileName FileName
Definition: fatprocs.h:884
UNICODE_STRING SmpSubsystemName
Definition: sminit.c:18
NTSTATUS NTAPI NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: obdir.c:731
ULONG SmpInitProgressByLine
Definition: sminit.c:31
DWORD *typedef HANDLE
Definition: winlogon.h:61
ULONG SmpAllowProtectedRenames
Definition: sminit.c:40
PRTL_UNICODE_STRING_BUFFER Path
RTL_QUERY_REGISTRY_TABLE SmpRegistryConfigurationTable[]
Definition: sminit.c:597
#define STATUS_INVALID_IMPORT_OF_NON_DLL
Definition: ntstatus.h:907
HANDLE SmpSessionsObjectDirectory
Definition: smsessn.c:31
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
NTSTATUS NTAPI NtSetInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, IN PVOID ProcessInformation, IN ULONG ProcessInformationLength)
Definition: query.c:1089
PVOID SecurityDescriptor
Definition: umtypes.h:187
UNICODE_STRING Os2Name
Definition: sminit.c:18
#define NtCurrentPeb()
Definition: FLS.c:19
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS NTAPI SmpInitializeKnownDlls(VOID)
Definition: sminit.c:1616
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
struct _KEY_VALUE_PARTIAL_INFORMATION KEY_VALUE_PARTIAL_INFORMATION
static const char const char * DllPath
Definition: image.c:34
ULONG SmpNextSessionIdScanMode
Definition: smsessn.c:29
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DIRECTORY_ALL_ACCESS
Definition: nt_native.h:1259
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
NTSTATUS NTAPI SmpConfigureSubSystems(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:524
#define SystemBasicInformation
Definition: xboxvmp.h:35
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
VOID NTAPI SmpProcessModuleImports(IN PVOID Unused, IN PCHAR ImportName)
Definition: sminit.c:1349
NTSTATUS NTAPI SmpConfigureObjectDirectories(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:271
unsigned int * PULONG
Definition: retypes.h:1
#define SECURITY_RESTRICTED_CODE_RID
Definition: setypes.h:541
LIST_ENTRY SmpSubSystemsToDefer
Definition: sminit.c:22
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define DPRINT1
Definition: precomp.h:8
BOOLEAN MiniNTBoot
Definition: sminit.c:41
NTSTATUS NTAPI SmpTerminate(IN PULONG_PTR Parameters, IN ULONG ParameterMask, IN ULONG ParameterCount)
Definition: smss.c:391
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
NTSTATUS NTAPI SmpConfigureDosDevices(IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
Definition: sminit.c:416
SECURITY_DESCRIPTOR SmpLiberalSDBody
Definition: sminit.c:35
ULONG SmpProtectionMode
Definition: sminit.c:40
NTSTATUS NTAPI SmpCreateSecurityDescriptors(IN BOOLEAN InitialCall)
Definition: sminit.c:941
ULONG SmpNextSessionId
Definition: smsessn.c:28
#define OUT
Definition: typedefs.h:39
PSMP_REGISTRY_VALUE NTAPI SmpFindRegistryValue(IN PLIST_ENTRY List, IN PWSTR ValueName)
Definition: sminit.c:188
SECURITY_DESCRIPTOR SmpApiPortSDBody
Definition: sminit.c:36
struct tagContext Context
Definition: acpixf.h:1027
unsigned int ULONG
Definition: retypes.h:1
base for all directory entries
Definition: entries.h:138
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define SEC_IMAGE
Definition: mmtypes.h:96
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
LIST_ENTRY SmpSubSystemList
Definition: sminit.c:21
#define INHERIT_ONLY_ACE
Definition: setypes.h:717
NTSTATUS NTAPI SmpInitializeDosDevices(VOID)
Definition: sminit.c:1245
PWCHAR SmpDefaultLibPathBuffer
Definition: sminit.c:27
#define REG_NONE
Definition: nt_native.h:1492
_In_ FILTER_INFORMATION_CLASS InformationClass
Definition: fltkernel.h:1714
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
#define GENERIC_EXECUTE
Definition: nt_native.h:91
return STATUS_SUCCESS
Definition: btrfs.c:2710
UNICODE_STRING Value
Definition: smss.h:54
UNICODE_STRING SmpAutoChkKeyword
Definition: smutil.c:34
#define REG_DWORD
Definition: sdbapi.c:539
#define DOMAIN_ALIAS_RID_ADMINS
Definition: setypes.h:624
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
NTSTATUS NTAPI SmpCreatePagingFileDescriptor(IN PUNICODE_STRING PageFileToken)
Definition: pagefile.c:84
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJECT_INHERIT_ACE
Definition: setypes.h:714
LIST_ENTRY SmpKnownDllsList
Definition: sminit.c:20
base of all file and directory entries
Definition: entries.h:82
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_In_ ULONG AclLength
Definition: rtlfuncs.h:1844
NTSTATUS NTAPI SmpLoadDataFromRegistry(OUT PUNICODE_STRING InitialCommand)
Definition: sminit.c:2186
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
Definition: iofunc.c:2932
RTL_CRITICAL_SECTION SmpKnownSubSysLock
Definition: smsubsys.c:18
#define SECURITY_CREATOR_SID_AUTHORITY
Definition: setypes.h:505
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
LIST_ENTRY SmpKnownSubSysHead
Definition: smsubsys.c:19
SID_IDENTIFIER_AUTHORITY NtAuthority
Definition: database.c:19
#define DELETE
Definition: nt_native.h:57
IN PUNICODE_STRING PortName
Definition: conport.c:35
#define REG_SZ
Definition: layer.c:22
_Out_ PHANDLE EventHandle
Definition: iofuncs.h:855