ReactOS  0.4.15-dev-5488-ge316d61
cmboot.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * PURPOSE: Configuration Manager - Boot Initialization
5  * COPYRIGHT: Copyright 2007 Alex Ionescu (alex.ionescu@reactos.org)
6  * Copyright 2010 ReactOS Portable Systems Group
7  * Copyright 2022 Hermès Bélusca-Maïto
8  *
9  * NOTE: This module is shared by both the kernel and the bootloader.
10  */
11 
12 /* INCLUDES *******************************************************************/
13 
14 #include <ntoskrnl.h>
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 #ifdef _BLDR_
20 
21 #undef CODE_SEG
22 #define CODE_SEG(...)
23 
24 #include <ntstrsafe.h>
25 #include <cmlib.h>
26 #include "internal/cmboot.h"
27 
28 // HACK: This is part of non-NT-compatible SafeBoot support in kernel.
30 
31 DBG_DEFAULT_CHANNEL(REGISTRY);
32 #define CMTRACE(x, fmt, ...) TRACE(fmt, ##__VA_ARGS__) // DPRINT
33 
34 #endif /* _BLDR_ */
35 
36 
37 /* DEFINES ********************************************************************/
38 
39 #define CM_BOOT_DEBUG 0x20
40 
41 #define IS_NULL_TERMINATED(Buffer, Size) \
42  (((Size) >= sizeof(WCHAR)) && ((Buffer)[(Size) / sizeof(WCHAR) - 1] == UNICODE_NULL))
43 
44 
45 /* FUNCTIONS ******************************************************************/
46 
47 // HACK: This is part of non-NT-compatible SafeBoot support in kernel.
48 extern ULONG InitSafeBootMode;
49 
50 CODE_SEG("INIT")
51 static
52 BOOLEAN
53 CmpIsSafe(
54  _In_ PHHIVE Hive,
55  _In_ HCELL_INDEX SafeBootCell,
56  _In_ HCELL_INDEX DriverCell);
57 
81 CODE_SEG("INIT")
83 NTAPI
86  _In_ HCELL_INDEX RootCell,
87  _In_ PCUNICODE_STRING SelectKeyName,
88  _Out_ PBOOLEAN AutoSelect)
89 {
92  HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
93  HCELL_INDEX CurrentValueCell;
95  ULONG Length;
97  PULONG CurrentData;
98  PULONG ControlSetId;
99  WCHAR Buffer[128];
100 
101  /* Sanity check: We shouldn't need to release any acquired cells */
103 
104  /* Get the Select key */
105  RtlInitUnicodeString(&Name, L"select");
106  Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
107  if (!Node) return HCELL_NIL;
108  SelectCell = CmpFindSubKeyByName(SystemHive, Node, &Name);
109  if (SelectCell == HCELL_NIL) return HCELL_NIL;
110 
111  /* Get AutoSelect value */
112  RtlInitUnicodeString(&Name, L"AutoSelect");
113  Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
114  if (!Node) return HCELL_NIL;
115  AutoSelectCell = CmpFindValueByName(SystemHive, Node, &Name);
116  if (AutoSelectCell == HCELL_NIL)
117  {
118  /* Assume TRUE if the value is missing */
119  *AutoSelect = TRUE;
120  }
121  else
122  {
123  /* Read the value */
124  Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
125  if (!Value) return HCELL_NIL;
126  // if (Value->Type != REG_DWORD) return HCELL_NIL;
127 
128  /* Convert it to a boolean */
129  CurrentData = (PULONG)CmpValueToData(SystemHive, Value, &Length);
130  if (!CurrentData) return HCELL_NIL;
131  // if (Length < sizeof(ULONG)) return HCELL_NIL;
132 
133  *AutoSelect = *(PBOOLEAN)CurrentData;
134  }
135 
136  /* Now find the control set being looked up */
137  Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
138  if (!Node) return HCELL_NIL;
139  SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
140  if (SelectValueCell == HCELL_NIL) return HCELL_NIL;
141 
142  /* Read the value (corresponding to the CCS ID) */
143  Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
144  if (!Value) return HCELL_NIL;
145  if (Value->Type != REG_DWORD) return HCELL_NIL;
146  ControlSetId = (PULONG)CmpValueToData(SystemHive, Value, &Length);
147  if (!ControlSetId) return HCELL_NIL;
148  if (Length < sizeof(ULONG)) return HCELL_NIL;
149 
150  /* Now build the CCS's Name */
152  L"ControlSet%03lu", *ControlSetId);
153  if (!NT_SUCCESS(Status)) return HCELL_NIL;
154  /* RtlStringCbPrintfW ensures the buffer to be NULL-terminated */
156 
157  /* Now open it */
158  Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
159  if (!Node) return HCELL_NIL;
160  ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &Name);
161  if (ControlSetCell == HCELL_NIL) return HCELL_NIL;
162 
163  /* Get the value of the "Current" CCS */
164  RtlInitUnicodeString(&Name, L"Current");
165  Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
166  if (!Node) return HCELL_NIL;
167  CurrentValueCell = CmpFindValueByName(SystemHive, Node, &Name);
168 
169  /* Make sure it exists */
170  if (CurrentValueCell != HCELL_NIL)
171  {
172  /* Get the current value and make sure it's a ULONG */
173  Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
174  if (!Value) return HCELL_NIL;
175  if (Value->Type == REG_DWORD)
176  {
177  /* Get the data and update it */
178  CurrentData = (PULONG)CmpValueToData(SystemHive, Value, &Length);
179  if (!CurrentData) return HCELL_NIL;
180  if (Length < sizeof(ULONG)) return HCELL_NIL;
181 
182  *CurrentData = *ControlSetId;
183  }
184  }
185 
186  /* Return the CCS cell */
187  return ControlSetCell;
188 }
189 
212 CODE_SEG("INIT")
213 static
214 ULONG
216  _In_ PHHIVE Hive,
217  _In_ HCELL_INDEX TagCell,
218  _In_ HCELL_INDEX GroupOrderCell,
219  _In_ PCUNICODE_STRING GroupName)
220 {
221  PCM_KEY_VALUE TagValue, Value;
223  HCELL_INDEX OrderCell;
224  PULONG DriverTag, TagOrder;
225  ULONG CurrentTag, Length;
226  BOOLEAN BufferAllocated;
227 
228  /* Sanity check: We shouldn't need to release any acquired cells */
229  ASSERT(Hive->ReleaseCellRoutine == NULL);
230 
231  /* Get the tag */
232  Value = (PCM_KEY_VALUE)HvGetCell(Hive, TagCell);
233  if (!Value) return -2;
234  if (Value->Type != REG_DWORD) return -2;
235  DriverTag = (PULONG)CmpValueToData(Hive, Value, &Length);
236  if (!DriverTag) return -2;
237  if (Length < sizeof(ULONG)) return -2;
238 
239  /* Get the order array */
240  Node = (PCM_KEY_NODE)HvGetCell(Hive, GroupOrderCell);
241  if (!Node) return -2;
242  OrderCell = CmpFindValueByName(Hive, Node, GroupName);
243  if (OrderCell == HCELL_NIL) return -2;
244 
245  /* And read it */
246  TagValue = (PCM_KEY_VALUE)HvGetCell(Hive, OrderCell);
247  if (!TagValue) return -2;
248  if (!CmpGetValueData(Hive,
249  TagValue,
250  &Length,
251  (PVOID*)&TagOrder,
252  &BufferAllocated,
253  &OrderCell)
254  || !TagOrder)
255  {
256  return -2;
257  }
258 
259  /* Parse each tag */
260  for (CurrentTag = 1; CurrentTag <= TagOrder[0]; CurrentTag++)
261  {
262  /* Find a match */
263  if (TagOrder[CurrentTag] == *DriverTag)
264  {
265  /* Found it -- return the tag */
266  if (BufferAllocated) Hive->Free(TagOrder, Length);
267  return CurrentTag;
268  }
269  }
270 
271  /* No matches, so assume next to last ordering */
272  if (BufferAllocated) Hive->Free(TagOrder, Length);
273  return -2;
274 }
275 
276 #ifdef _BLDR_
277 
298 CODE_SEG("INIT")
299 BOOLEAN
300 NTAPI
301 CmpIsDriverInList(
302  _In_ PLIST_ENTRY DriverListHead,
303  _In_ PCUNICODE_STRING DriverName,
304  _Out_opt_ PBOOT_DRIVER_NODE* FoundDriver)
305 {
307  PBOOT_DRIVER_NODE DriverNode;
308 
309  for (Entry = DriverListHead->Flink;
310  Entry != DriverListHead;
311  Entry = Entry->Flink)
312  {
313  DriverNode = CONTAINING_RECORD(Entry,
315  ListEntry.Link);
316 
317  if (RtlEqualUnicodeString(&DriverNode->Name,
318  DriverName,
319  TRUE))
320  {
321  /* The driver node has been found */
322  if (FoundDriver)
323  *FoundDriver = DriverNode;
324  return TRUE;
325  }
326  }
327 
328  /* None has been found */
329  if (FoundDriver)
330  *FoundDriver = NULL;
331  return FALSE;
332 }
333 
334 #endif /* _BLDR_ */
335 
361 CODE_SEG("INIT")
362 BOOLEAN
363 NTAPI
365  _In_ PHHIVE Hive,
366  _In_ HCELL_INDEX DriverCell,
367  _In_ HCELL_INDEX GroupOrderCell,
369  _Inout_ PLIST_ENTRY DriverListHead)
370 {
371  PBOOT_DRIVER_NODE DriverNode;
375  ULONG Length;
376  USHORT NameLength;
377  HCELL_INDEX ValueCell, TagCell;
378  PUNICODE_STRING FilePath, RegistryString;
380  PULONG ErrorControl;
381  PWCHAR Buffer;
382 
383  /* Sanity check: We shouldn't need to release any acquired cells */
384  ASSERT(Hive->ReleaseCellRoutine == NULL);
385 
386  /* Allocate a driver node and initialize it */
387  DriverNode = Hive->Allocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM);
388  if (!DriverNode)
389  return FALSE;
390 
391  RtlZeroMemory(DriverNode, sizeof(BOOT_DRIVER_NODE));
392  DriverEntry = &DriverNode->ListEntry;
393 
394  /* Get the driver cell */
395  Node = (PCM_KEY_NODE)HvGetCell(Hive, DriverCell);
396  if (!Node)
397  goto Failure;
398 
399  /* Get the name from the cell */
400  NameLength = (Node->Flags & KEY_COMP_NAME) ?
401  CmpCompressedNameSize(Node->Name, Node->NameLength) :
402  Node->NameLength;
403  if (NameLength < sizeof(WCHAR))
404  goto Failure;
405 
406  /* Now allocate the buffer for it and copy the name */
407  RtlInitEmptyUnicodeString(&DriverNode->Name,
408  Hive->Allocate(NameLength, FALSE, TAG_CM),
409  NameLength);
410  if (!DriverNode->Name.Buffer)
411  goto Failure;
412 
413  DriverNode->Name.Length = NameLength;
414  if (Node->Flags & KEY_COMP_NAME)
415  {
416  /* Compressed name */
417  CmpCopyCompressedName(DriverNode->Name.Buffer,
418  DriverNode->Name.Length,
419  Node->Name,
420  Node->NameLength);
421  }
422  else
423  {
424  /* Normal name */
425  RtlCopyMemory(DriverNode->Name.Buffer, Node->Name, Node->NameLength);
426  }
427 
428  /* Now find the image path */
429  RtlInitUnicodeString(&Name, L"ImagePath");
430  ValueCell = CmpFindValueByName(Hive, Node, &Name);
431  if (ValueCell == HCELL_NIL)
432  {
433  /* Could not find it, so assume the drivers path */
434  Length = sizeof(L"System32\\Drivers\\") + NameLength + sizeof(L".sys");
435 
436  /* Allocate the path name */
437  FilePath = &DriverEntry->FilePath;
438  RtlInitEmptyUnicodeString(FilePath,
439  Hive->Allocate(Length, FALSE, TAG_CM),
440  (USHORT)Length);
441  if (!FilePath->Buffer)
442  goto Failure;
443 
444  /* Write the path name */
445  if (!NT_SUCCESS(RtlAppendUnicodeToString(FilePath, L"System32\\Drivers\\")) ||
448  {
449  goto Failure;
450  }
451  }
452  else
453  {
454  /* Path name exists, so grab it */
455  Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
456  if (!Value)
457  goto Failure;
458  if ((Value->Type != REG_SZ) && (Value->Type != REG_EXPAND_SZ))
459  goto Failure;
461  if (!Buffer)
462  goto Failure;
464  Length -= sizeof(UNICODE_NULL);
465  if (Length < sizeof(WCHAR))
466  goto Failure;
467 
468  /* Allocate and setup the path name */
469  FilePath = &DriverEntry->FilePath;
470  RtlInitEmptyUnicodeString(FilePath,
471  Hive->Allocate(Length, FALSE, TAG_CM),
472  (USHORT)Length);
473  if (!FilePath->Buffer)
474  goto Failure;
475 
476  /* Transfer the data */
477  RtlCopyMemory(FilePath->Buffer, Buffer, Length);
478  FilePath->Length = (USHORT)Length;
479  }
480 
481  /* Now build the registry path */
482  RegistryString = &DriverEntry->RegistryPath;
483  Length = RegistryPath->Length + NameLength;
484  RtlInitEmptyUnicodeString(RegistryString,
485  Hive->Allocate(Length, FALSE, TAG_CM),
486  (USHORT)Length);
487  if (!RegistryString->Buffer)
488  goto Failure;
489 
490  /* Add the driver name to it */
491  if (!NT_SUCCESS(RtlAppendUnicodeStringToString(RegistryString, RegistryPath)) ||
492  !NT_SUCCESS(RtlAppendUnicodeStringToString(RegistryString, &DriverNode->Name)))
493  {
494  goto Failure;
495  }
496 
497  /* The entry is done, add it */
498  InsertHeadList(DriverListHead, &DriverEntry->Link);
499 
500  /* Now find error control settings */
501  RtlInitUnicodeString(&Name, L"ErrorControl");
502  ValueCell = CmpFindValueByName(Hive, Node, &Name);
503  if (ValueCell == HCELL_NIL)
504  {
505  /* Could not find it, so assume default */
506  DriverNode->ErrorControl = NormalError;
507  }
508  else
509  {
510  /* Otherwise, read whatever the data says */
511  Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
512  if (!Value)
513  goto Failure;
514  if (Value->Type != REG_DWORD)
515  goto Failure;
516  ErrorControl = (PULONG)CmpValueToData(Hive, Value, &Length);
517  if (!ErrorControl)
518  goto Failure;
519  if (Length < sizeof(ULONG))
520  goto Failure;
521 
522  DriverNode->ErrorControl = *ErrorControl;
523  }
524 
525  /* Next, get the group cell */
526  RtlInitUnicodeString(&Name, L"group");
527  ValueCell = CmpFindValueByName(Hive, Node, &Name);
528  if (ValueCell == HCELL_NIL)
529  {
530  /* Could not find it, so set an empty string */
531  RtlInitEmptyUnicodeString(&DriverNode->Group, NULL, 0);
532  }
533  else
534  {
535  /* Found it, read the group value */
536  Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
537  if (!Value)
538  goto Failure;
539  if (Value->Type != REG_SZ) // REG_EXPAND_SZ not really allowed there.
540  goto Failure;
541 
542  /* Copy it into the node */
544  if (!Buffer)
545  goto Failure;
547  Length -= sizeof(UNICODE_NULL);
548 
549  DriverNode->Group.Buffer = Buffer;
550  DriverNode->Group.Length = (USHORT)Length;
551  DriverNode->Group.MaximumLength = DriverNode->Group.Length;
552  }
553 
554  /* Finally, find the tag */
555  RtlInitUnicodeString(&Name, L"Tag");
556  TagCell = CmpFindValueByName(Hive, Node, &Name);
557  if (TagCell == HCELL_NIL)
558  {
559  /* No tag, so load last */
560  DriverNode->Tag = -1;
561  }
562  else
563  {
564  /* Otherwise, decode it based on tag order */
565  DriverNode->Tag = CmpFindTagIndex(Hive,
566  TagCell,
567  GroupOrderCell,
568  &DriverNode->Group);
569  }
570 
571  CMTRACE(CM_BOOT_DEBUG, "Adding boot driver: '%wZ', '%wZ'\n",
572  &DriverNode->Name, &DriverEntry->FilePath);
573 
574  /* All done! */
575  return TRUE;
576 
577 Failure:
578  if (DriverEntry->RegistryPath.Buffer)
579  {
580  Hive->Free(DriverEntry->RegistryPath.Buffer,
581  DriverEntry->RegistryPath.MaximumLength);
582  }
583  if (DriverEntry->FilePath.Buffer)
584  {
585  Hive->Free(DriverEntry->FilePath.Buffer,
586  DriverEntry->FilePath.MaximumLength);
587  }
588  if (DriverNode->Name.Buffer)
589  {
590  Hive->Free(DriverNode->Name.Buffer,
591  DriverNode->Name.MaximumLength);
592  }
593  Hive->Free(DriverNode, sizeof(BOOT_DRIVER_NODE));
594 
595  return FALSE;
596 }
597 
615 CODE_SEG("INIT")
616 static
617 BOOLEAN
619  _In_ PHHIVE Hive,
620  _In_ HCELL_INDEX Cell,
621  _In_ SERVICE_LOAD_TYPE LoadType)
622 {
626  HCELL_INDEX ValueCell;
627  ULONG Length;
628  PULONG Data;
629 
630  /* Sanity check: We shouldn't need to release any acquired cells */
631  ASSERT(Hive->ReleaseCellRoutine == NULL);
632 
633  /* Open the start cell */
634  Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
635  if (!Node) return FALSE;
636  ValueCell = CmpFindValueByName(Hive, Node, &Name);
637  if (ValueCell == HCELL_NIL) return FALSE;
638 
639  /* Read the start value */
640  Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
641  if (!Value) return FALSE;
642  if (Value->Type != REG_DWORD) return FALSE;
643  Data = (PULONG)CmpValueToData(Hive, Value, &Length);
644  if (!Data) return FALSE;
645  if (Length < sizeof(ULONG)) return FALSE;
646 
647  /* Return if the type matches */
648  return (*Data == LoadType);
649 }
650 
676 CODE_SEG("INIT")
677 BOOLEAN
678 NTAPI
680  _In_ PHHIVE Hive,
681  _In_ HCELL_INDEX ControlSet,
682  _In_ SERVICE_LOAD_TYPE LoadType,
684  _Inout_ PLIST_ENTRY DriverListHead)
685 {
686  HCELL_INDEX ServicesCell, ControlCell, GroupOrderCell, DriverCell;
687  HCELL_INDEX SafeBootCell = HCELL_NIL;
688  ULONG i;
690  UNICODE_STRING KeyPath;
691  PCM_KEY_NODE ControlNode, ServicesNode, Node;
692  PBOOT_DRIVER_NODE FsNode;
693 
694  /* Sanity check: We shouldn't need to release any acquired cells */
695  ASSERT(Hive->ReleaseCellRoutine == NULL);
696 
697  /* Open the control set key */
698  ControlNode = (PCM_KEY_NODE)HvGetCell(Hive, ControlSet);
699  if (!ControlNode) return FALSE;
700 
701  /* Get services cell */
702  RtlInitUnicodeString(&Name, L"Services");
703  ServicesCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
704  if (ServicesCell == HCELL_NIL) return FALSE;
705 
706  /* Open services key */
707  ServicesNode = (PCM_KEY_NODE)HvGetCell(Hive, ServicesCell);
708  if (!ServicesNode) return FALSE;
709 
710  /* Get control cell */
711  RtlInitUnicodeString(&Name, L"Control");
712  ControlCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
713  if (ControlCell == HCELL_NIL) return FALSE;
714 
715  /* Get the group order cell and read it */
716  Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlCell);
717  if (!Node) return FALSE;
718  RtlInitUnicodeString(&Name, L"GroupOrderList");
719  GroupOrderCell = CmpFindSubKeyByName(Hive, Node, &Name);
720  if (GroupOrderCell == HCELL_NIL) return FALSE;
721 
722  /* Get Safe Boot cell */
723  if (InitSafeBootMode)
724  {
725  /* Open the Safe Boot key */
726  RtlInitUnicodeString(&Name, L"SafeBoot");
727  Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlCell);
728  if (!Node) return FALSE;
729  SafeBootCell = CmpFindSubKeyByName(Hive, Node, &Name);
730  if (SafeBootCell == HCELL_NIL) return FALSE;
731 
732  /* Open the correct start key (depending on the mode) */
733  Node = (PCM_KEY_NODE)HvGetCell(Hive, SafeBootCell);
734  if (!Node) return FALSE;
735  switch (InitSafeBootMode)
736  {
737  /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
738  case 1:
739  case 3: RtlInitUnicodeString(&Name, L"Minimal"); break;
740  case 2: RtlInitUnicodeString(&Name, L"Network"); break;
741  default: return FALSE;
742  }
743  SafeBootCell = CmpFindSubKeyByName(Hive, Node, &Name);
744  if (SafeBootCell == HCELL_NIL) return FALSE;
745  }
746 
747  /* Build the root registry path */
748  RtlInitUnicodeString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
749 
750  /* Enumerate each sub-key */
751  i = 0;
752  DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, i);
753  while (DriverCell != HCELL_NIL)
754  {
755  /* Make sure it's a driver of this start type AND is "safe" to load */
756  if (CmpIsLoadType(Hive, DriverCell, LoadType) &&
757  CmpIsSafe(Hive, SafeBootCell, DriverCell))
758  {
759  /* Add it to the list */
760  if (!CmpAddDriverToList(Hive,
761  DriverCell,
762  GroupOrderCell,
763  &KeyPath,
764  DriverListHead))
765  {
766  CMTRACE(CM_BOOT_DEBUG, " Failed to add boot driver\n");
767  }
768  }
769 
770  /* Go to the next sub-key */
771  DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, ++i);
772  }
773 
774  /* Check if we have a boot file system */
775  if (BootFileSystem)
776  {
777  /* Find it */
779  DriverCell = CmpFindSubKeyByName(Hive, ServicesNode, &Name);
780  if (DriverCell != HCELL_NIL)
781  {
782  CMTRACE(CM_BOOT_DEBUG, "Adding Boot FileSystem '%S'\n",
784 
785  /* Always add it to the list */
786  if (!CmpAddDriverToList(Hive,
787  DriverCell,
788  GroupOrderCell,
789  &KeyPath,
790  DriverListHead))
791  {
792  CMTRACE(CM_BOOT_DEBUG, " Failed to add boot driver\n");
793  }
794  else
795  {
796  /* Mark it as critical so it always loads */
797  FsNode = CONTAINING_RECORD(DriverListHead->Flink,
799  ListEntry.Link);
801  }
802  }
803  }
804 
805  /* We're done! */
806  return TRUE;
807 }
808 
825 CODE_SEG("INIT")
826 static
827 BOOLEAN
829  _Inout_ PLIST_ENTRY DriverListHead,
830  _In_ PCUNICODE_STRING OrderList)
831 {
832  PWCHAR Current, End = NULL;
833  UNICODE_STRING GroupName;
834  PLIST_ENTRY NextEntry;
835  PBOOT_DRIVER_NODE CurrentNode;
836 
837  /* We're going from end to start, so get to the last group and keep going */
838  Current = &OrderList->Buffer[OrderList->Length / sizeof(WCHAR)];
839  while (Current > OrderList->Buffer)
840  {
841  /* Scan the current string */
842  do
843  {
844  if (*Current == UNICODE_NULL) End = Current;
845  } while ((*(--Current - 1) != UNICODE_NULL) && (Current != OrderList->Buffer));
846 
847  /* This is our cleaned up string for this specific group */
848  ASSERT(End != NULL);
849  GroupName.Length = (USHORT)(End - Current) * sizeof(WCHAR);
850  GroupName.MaximumLength = GroupName.Length;
851  GroupName.Buffer = Current;
852 
853  /* Now loop the driver list */
854  NextEntry = DriverListHead->Flink;
855  while (NextEntry != DriverListHead)
856  {
857  /* Get this node */
858  CurrentNode = CONTAINING_RECORD(NextEntry,
860  ListEntry.Link);
861 
862  /* Get the next entry now since we'll do a relink */
863  NextEntry = NextEntry->Flink;
864 
865  /* Is there a group name and does it match the current group? */
866  if (CurrentNode->Group.Buffer &&
867  RtlEqualUnicodeString(&GroupName, &CurrentNode->Group, TRUE))
868  {
869  /* Remove from this location and re-link in the new one */
870  RemoveEntryList(&CurrentNode->ListEntry.Link);
871  InsertHeadList(DriverListHead, &CurrentNode->ListEntry.Link);
872  }
873  }
874 
875  /* Move on */
876  --Current;
877  }
878 
879  /* All done */
880  return TRUE;
881 }
882 
899 CODE_SEG("INIT")
900 BOOLEAN
901 NTAPI
903  _In_ PHHIVE Hive,
904  _In_ HCELL_INDEX ControlSet,
905  _Inout_ PLIST_ENTRY DriverListHead)
906 {
908  PCM_KEY_VALUE ListValue;
909  HCELL_INDEX ControlCell, GroupOrder, ListCell;
910  UNICODE_STRING Name, OrderList;
911  ULONG Length;
912 
913  /* Sanity check: We shouldn't need to release any acquired cells */
914  ASSERT(Hive->ReleaseCellRoutine == NULL);
915 
916  /* Open the control key */
917  Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlSet);
918  if (!Node) return FALSE;
919  RtlInitUnicodeString(&Name, L"Control");
920  ControlCell = CmpFindSubKeyByName(Hive, Node, &Name);
921  if (ControlCell == HCELL_NIL) return FALSE;
922 
923  /* Open the service group order */
924  Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlCell);
925  if (!Node) return FALSE;
926  RtlInitUnicodeString(&Name, L"ServiceGroupOrder");
927  GroupOrder = CmpFindSubKeyByName(Hive, Node, &Name);
928  if (GroupOrder == HCELL_NIL) return FALSE;
929 
930  /* Open the list key */
931  Node = (PCM_KEY_NODE)HvGetCell(Hive, GroupOrder);
932  if (!Node) return FALSE;
933  RtlInitUnicodeString(&Name, L"list");
934  ListCell = CmpFindValueByName(Hive, Node, &Name);
935  if (ListCell == HCELL_NIL) return FALSE;
936 
937  /* Read the actual list */
938  ListValue = (PCM_KEY_VALUE)HvGetCell(Hive, ListCell);
939  if (!ListValue) return FALSE;
940  if (ListValue->Type != REG_MULTI_SZ) return FALSE;
941 
942  /* Copy it into a buffer */
943  OrderList.Buffer = (PWCHAR)CmpValueToData(Hive, ListValue, &Length);
944  if (!OrderList.Buffer) return FALSE;
945  if (!IS_NULL_TERMINATED(OrderList.Buffer, Length)) return FALSE;
946  OrderList.Length = (USHORT)Length - sizeof(UNICODE_NULL);
947  OrderList.MaximumLength = OrderList.Length;
948 
949  /* And start the sort algorithm */
950  return CmpDoSort(DriverListHead, &OrderList);
951 }
952 
953 CODE_SEG("INIT")
954 static
955 BOOLEAN
957  _In_ PBOOT_DRIVER_NODE StartNode,
958  _In_ PBOOT_DRIVER_NODE EndNode)
959 {
960  PBOOT_DRIVER_NODE CurrentNode, PreviousNode;
961  PLIST_ENTRY ListEntry;
962 
963  /* Base case, nothing to do */
964  if (StartNode == EndNode) return TRUE;
965 
966  /* Loop the nodes */
967  CurrentNode = StartNode;
968  do
969  {
970  /* Save this as the previous node */
971  PreviousNode = CurrentNode;
972 
973  /* And move to the next one */
974  ListEntry = CurrentNode->ListEntry.Link.Flink;
975  CurrentNode = CONTAINING_RECORD(ListEntry,
977  ListEntry.Link);
978 
979  /* Check if the previous driver had a bigger tag */
980  if (PreviousNode->Tag > CurrentNode->Tag)
981  {
982  /* Check if we need to update the tail */
983  if (CurrentNode == EndNode)
984  {
985  /* Update the tail */
986  ListEntry = CurrentNode->ListEntry.Link.Blink;
987  EndNode = CONTAINING_RECORD(ListEntry,
989  ListEntry.Link);
990  }
991 
992  /* Remove this driver since we need to move it */
993  RemoveEntryList(&CurrentNode->ListEntry.Link);
994 
995  /* Keep looping until we find a driver with a lower tag than ours */
996  while ((PreviousNode->Tag > CurrentNode->Tag) && (PreviousNode != StartNode))
997  {
998  /* We'll be re-inserted at this spot */
999  ListEntry = PreviousNode->ListEntry.Link.Blink;
1000  PreviousNode = CONTAINING_RECORD(ListEntry,
1002  ListEntry.Link);
1003  }
1004 
1005  /* Do the insert in the new location */
1006  InsertTailList(&PreviousNode->ListEntry.Link, &CurrentNode->ListEntry.Link);
1007 
1008  /* Update the head, if needed */
1009  if (PreviousNode == StartNode) StartNode = CurrentNode;
1010  }
1011  } while (CurrentNode != EndNode);
1012 
1013  /* All done */
1014  return TRUE;
1015 }
1016 
1027 CODE_SEG("INIT")
1028 BOOLEAN
1029 NTAPI
1031  _Inout_ PLIST_ENTRY DriverListHead)
1032 {
1033  PLIST_ENTRY NextEntry;
1034  PBOOT_DRIVER_NODE StartNode, EndNode, CurrentNode;
1035 
1036  /* Loop the list */
1037  NextEntry = DriverListHead->Flink;
1038  while (NextEntry != DriverListHead)
1039  {
1040  /* Find the first entry */
1041  StartNode = CONTAINING_RECORD(NextEntry,
1043  ListEntry.Link);
1044  do
1045  {
1046  /* Find the last entry */
1047  EndNode = CONTAINING_RECORD(NextEntry,
1049  ListEntry.Link);
1050 
1051  /* Get the next entry */
1052  NextEntry = NextEntry->Flink;
1053  CurrentNode = CONTAINING_RECORD(NextEntry,
1055  ListEntry.Link);
1056 
1057  /* If the next entry is back to the top, break out */
1058  if (NextEntry == DriverListHead) break;
1059 
1060  /* Otherwise, check if this entry is equal */
1061  if (!RtlEqualUnicodeString(&StartNode->Group,
1062  &CurrentNode->Group,
1063  TRUE))
1064  {
1065  /* It is, so we've detected a cycle, break out */
1066  break;
1067  }
1068  } while (NextEntry != DriverListHead);
1069 
1070  /* Now we have the correct start and end pointers, so do the sort */
1071  CmpOrderGroup(StartNode, EndNode);
1072  }
1073 
1074  /* We're done */
1075  return TRUE;
1076 }
1077 
1078 CODE_SEG("INIT")
1079 static
1080 BOOLEAN
1082  _In_ PHHIVE Hive,
1083  _In_ HCELL_INDEX SafeBootCell,
1084  _In_ HCELL_INDEX DriverCell)
1085 {
1086  PCM_KEY_NODE SafeBootNode;
1087  PCM_KEY_NODE DriverNode;
1088  PCM_KEY_VALUE KeyValue;
1089  HCELL_INDEX CellIndex;
1090  ULONG Length;
1092  PWCHAR Buffer;
1093 
1094  /* Sanity check: We shouldn't need to release any acquired cells */
1095  ASSERT(Hive->ReleaseCellRoutine == NULL);
1096 
1097  /* Driver key node (mandatory) */
1098  ASSERT(DriverCell != HCELL_NIL);
1099  DriverNode = (PCM_KEY_NODE)HvGetCell(Hive, DriverCell);
1100  if (!DriverNode) return FALSE;
1101 
1102  /* Safe boot key node (optional but return TRUE if not present) */
1103  if (SafeBootCell == HCELL_NIL) return TRUE;
1104  SafeBootNode = (PCM_KEY_NODE)HvGetCell(Hive, SafeBootCell);
1105  if (!SafeBootNode) return FALSE;
1106 
1107  /* Search by the name from the group */
1108  RtlInitUnicodeString(&Name, L"Group");
1109  CellIndex = CmpFindValueByName(Hive, DriverNode, &Name);
1110  if (CellIndex != HCELL_NIL)
1111  {
1112  KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
1113  if (!KeyValue) return FALSE;
1114 
1115  if (KeyValue->Type == REG_SZ) // REG_EXPAND_SZ not really allowed there.
1116  {
1117  /* Compose the search 'key' */
1118  Buffer = (PWCHAR)CmpValueToData(Hive, KeyValue, &Length);
1119  if (!Buffer)
1120  return FALSE;
1122  Length -= sizeof(UNICODE_NULL);
1123 
1124  Name.Buffer = Buffer;
1125  Name.Length = (USHORT)Length;
1126  Name.MaximumLength = Name.Length;
1127 
1128  /* Search for corresponding key in the Safe Boot key */
1129  CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
1130  if (CellIndex != HCELL_NIL) return TRUE;
1131  }
1132  }
1133 
1134  /* Group has not been found - find driver name */
1135  Length = (DriverNode->Flags & KEY_COMP_NAME) ?
1136  CmpCompressedNameSize(DriverNode->Name, DriverNode->NameLength) :
1137  DriverNode->NameLength;
1138  if (Length < sizeof(WCHAR))
1139  return FALSE;
1140 
1141  /* Now allocate the buffer for it and copy the name */
1142  RtlInitEmptyUnicodeString(&Name,
1143  Hive->Allocate(Length, FALSE, TAG_CM),
1144  (USHORT)Length);
1145  if (!Name.Buffer)
1146  return FALSE;
1147 
1148  Name.Length = (USHORT)Length;
1149  if (DriverNode->Flags & KEY_COMP_NAME)
1150  {
1151  /* Compressed name */
1152  CmpCopyCompressedName(Name.Buffer,
1153  Name.Length,
1154  DriverNode->Name,
1155  DriverNode->NameLength);
1156  }
1157  else
1158  {
1159  /* Normal name */
1160  RtlCopyMemory(Name.Buffer, DriverNode->Name, DriverNode->NameLength);
1161  }
1162 
1163  CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
1164  Hive->Free(Name.Buffer, Name.MaximumLength);
1165  if (CellIndex != HCELL_NIL) return TRUE;
1166 
1167  /* Not group or driver name - search by image name */
1168  RtlInitUnicodeString(&Name, L"ImagePath");
1169  CellIndex = CmpFindValueByName(Hive, DriverNode, &Name);
1170  if (CellIndex != HCELL_NIL)
1171  {
1172  KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
1173  if (!KeyValue) return FALSE;
1174 
1175  if ((KeyValue->Type == REG_SZ) || (KeyValue->Type == REG_EXPAND_SZ))
1176  {
1177  /* Compose the search 'key' */
1178  Buffer = (PWCHAR)CmpValueToData(Hive, KeyValue, &Length);
1179  if (!Buffer) return FALSE;
1180  if (Length < sizeof(WCHAR)) return FALSE;
1181 
1182  /* Get the base image file name */
1183  // FIXME: wcsrchr() may fail if Buffer is *not* NULL-terminated!
1185  if (!Name.Buffer) return FALSE;
1186  ++Name.Buffer;
1187 
1188  /* Length of the base name must be >=1 WCHAR */
1189  if (((ULONG_PTR)Name.Buffer - (ULONG_PTR)Buffer) >= Length)
1190  return FALSE;
1191  Length -= ((ULONG_PTR)Name.Buffer - (ULONG_PTR)Buffer);
1192  if (IS_NULL_TERMINATED(Name.Buffer, Length))
1193  Length -= sizeof(UNICODE_NULL);
1194  if (Length < sizeof(WCHAR)) return FALSE;
1195 
1196  Name.Length = (USHORT)Length;
1197  Name.MaximumLength = Name.Length;
1198 
1199  /* Search for corresponding key in the Safe Boot key */
1200  CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
1201  if (CellIndex != HCELL_NIL) return TRUE;
1202  }
1203  }
1204 
1205  /* Nothing found - nothing else to search */
1206  return FALSE;
1207 }
1208 
1221 CODE_SEG("INIT")
1222 VOID
1223 NTAPI
1225  _In_ PHHIVE Hive,
1226  _Inout_ PLIST_ENTRY DriverListHead)
1227 {
1229  PBOOT_DRIVER_NODE DriverNode;
1230 
1231  /* Loop through the list and remove each driver node */
1232  while (!IsListEmpty(DriverListHead))
1233  {
1234  /* Get the driver node */
1235  Entry = RemoveHeadList(DriverListHead);
1236  DriverNode = CONTAINING_RECORD(Entry,
1238  ListEntry.Link);
1239 
1240  /* Free any allocated string buffers, then the node */
1241  if (DriverNode->ListEntry.RegistryPath.Buffer)
1242  {
1243  Hive->Free(DriverNode->ListEntry.RegistryPath.Buffer,
1244  DriverNode->ListEntry.RegistryPath.MaximumLength);
1245  }
1246  if (DriverNode->ListEntry.FilePath.Buffer)
1247  {
1248  Hive->Free(DriverNode->ListEntry.FilePath.Buffer,
1249  DriverNode->ListEntry.FilePath.MaximumLength);
1250  }
1251  if (DriverNode->Name.Buffer)
1252  {
1253  Hive->Free(DriverNode->Name.Buffer,
1254  DriverNode->Name.MaximumLength);
1255  }
1256  Hive->Free(DriverNode, sizeof(BOOT_DRIVER_NODE));
1257  }
1258 }
1259 
1260 /* EOF */
#define KEY_COMP_NAME
Definition: cmdata.h:35
const uint16_t * PCWSTR
Definition: typedefs.h:57
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
#define CMTRACE(x, fmt,...)
Definition: cm.h:40
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
BOOT_DRIVER_LIST_ENTRY ListEntry
Definition: cmboot.h:15
#define _In_opt_
Definition: ms_sal.h:309
#define _Inout_
Definition: ms_sal.h:378
struct _Entry Entry
Definition: kefuncs.h:629
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define _Out_
Definition: ms_sal.h:345
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define TRUE
Definition: types.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
ULONG ErrorControl
Definition: cmboot.h:19
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG _In_opt_ PVOID Data
Definition: wdfdevice.h:4527
BOOLEAN NTAPI CmpGetValueData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length, OUT PVOID *Buffer, OUT PBOOLEAN BufferAllocated, OUT PHCELL_INDEX CellToRelease)
Definition: cmvalue.c:125
enum _CM_SERVICE_LOAD_TYPE SERVICE_LOAD_TYPE
LONG NTSTATUS
Definition: precomp.h:26
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
Definition: cmindex.c:600
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:213
#define HCELL_NIL
Definition: hivedata.h:85
PHHIVE SystemHive
Definition: registry.c:32
BOOLEAN NTAPI CmpAddDriverToList(_In_ PHHIVE Hive, _In_ HCELL_INDEX DriverCell, _In_ HCELL_INDEX GroupOrderCell, _In_ PCUNICODE_STRING RegistryPath, _Inout_ PLIST_ENTRY DriverListHead)
Inserts the specified driver entry into the driver list.
Definition: cmboot.c:364
uint16_t * PWCHAR
Definition: typedefs.h:56
#define InsertTailList(ListHead, Entry)
UNICODE_STRING FilePath
Definition: arc.h:201
USHORT NameLength
Definition: cmdata.h:114
#define CM_BOOT_DEBUG
Definition: cmboot.c:39
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
PCWSTR FilePath
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:381
uint32_t ULONG_PTR
Definition: typedefs.h:65
Definition: arc.h:198
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI CmpFindDrivers(_In_ PHHIVE Hive, _In_ HCELL_INDEX ControlSet, _In_ SERVICE_LOAD_TYPE LoadType, _In_opt_ PCWSTR BootFileSystem, _Inout_ PLIST_ENTRY DriverListHead)
Enumerates all drivers within the given control set and load type, present in the "Services" sub-key,...
Definition: cmboot.c:679
static BOOLEAN CmpIsSafe(_In_ PHHIVE Hive, _In_ HCELL_INDEX SafeBootCell, _In_ HCELL_INDEX DriverCell)
Definition: cmboot.c:1081
#define L(x)
Definition: ntvdm.h:50
VOID NTAPI CmpFreeDriverList(_In_ PHHIVE Hive, _Inout_ PLIST_ENTRY DriverListHead)
Empties the driver list and frees all allocated driver nodes in it.
Definition: cmboot.c:1224
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 OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
union node Node
Definition: types.h:1255
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
#define REG_MULTI_SZ
Definition: nt_native.h:1501
BOOLEAN NTAPI CmpSortDriverList(_In_ PHHIVE Hive, _In_ HCELL_INDEX ControlSet, _Inout_ PLIST_ENTRY DriverListHead)
Sorts the driver list, according to the drivers' group load ordering.
Definition: cmboot.c:902
struct NameRec_ * Name
Definition: cdprocs.h:459
unsigned char BOOLEAN
struct _CM_KEY_NODE * PCM_KEY_NODE
#define _In_
Definition: ms_sal.h:308
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
static BOOLEAN CmpDoSort(_Inout_ PLIST_ENTRY DriverListHead, _In_ PCUNICODE_STRING OrderList)
Performs the driver list sorting, according to the ordering list.
Definition: cmboot.c:828
Definition: bufpool.h:45
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
PCWSTR BootFileSystem
Definition: winldr.c:30
static BOOLEAN CmpIsLoadType(_In_ PHHIVE Hive, _In_ HCELL_INDEX Cell, _In_ SERVICE_LOAD_TYPE LoadType)
Checks whether the specified driver has the expected load type.
Definition: cmboot.c:618
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
Status
Definition: gdiplustypes.h:24
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
UNICODE_STRING Name
Definition: cmboot.h:17
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTRSAFEVAPI RtlStringCbPrintfW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1173
static ULONG CmpFindTagIndex(_In_ PHHIVE Hive, _In_ HCELL_INDEX TagCell, _In_ HCELL_INDEX GroupOrderCell, _In_ PCUNICODE_STRING GroupName)
Finds the index of the driver's "Tag" value in its corresponding group ordering list.
Definition: cmboot.c:215
ULONG HCELL_INDEX
Definition: hivedata.h:80
static BOOLEAN CmpOrderGroup(_In_ PBOOT_DRIVER_NODE StartNode, _In_ PBOOT_DRIVER_NODE EndNode)
Definition: cmboot.c:956
#define TAG_CM
Definition: cmlib.h:205
char * PBOOLEAN
Definition: retypes.h:11
Definition: typedefs.h:119
#define wcsrchr
Definition: compat.h:16
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
BOOLEAN NTAPI CmpResolveDriverDependencies(_Inout_ PLIST_ENTRY DriverListHead)
Removes potential circular dependencies (cycles) and sorts the driver list.
Definition: cmboot.c:1030
UNICODE_STRING Group
Definition: cmboot.h:16
HCELL_INDEX NTAPI CmpFindControlSet(_In_ PHHIVE SystemHive, _In_ HCELL_INDEX RootCell, _In_ PCUNICODE_STRING SelectKeyName, _Out_ PBOOLEAN AutoSelect)
Finds the corresponding "HKLM\SYSTEM\ControlSetXXX" system control set registry key,...
Definition: cmboot.c:84
UNICODE_STRING RegistryPath
Definition: arc.h:202
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned short USHORT
Definition: pedump.c:61
HCELL_INDEX NTAPI CmpFindValueByName(IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PCUNICODE_STRING Name)
Definition: cmvalue.c:99
struct _CM_KEY_VALUE * PCM_KEY_VALUE
ULONG Type
Definition: cmdata.h:128
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define _Out_opt_
Definition: ms_sal.h:346
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
ULONG InitSafeBootMode
Definition: init.c:71
LIST_ENTRY Link
Definition: arc.h:200
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define SERVICE_ERROR_CRITICAL
Definition: cmtypes.h:984
#define IS_NULL_TERMINATED(Buffer, Size)
Definition: cmboot.c:41
#define REG_DWORD
Definition: sdbapi.c:596
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
PRELEASE_CELL_ROUTINE ReleaseCellRoutine
Definition: hivedata.h:292
base of all file and directory entries
Definition: entries.h:82
USHORT Flags
Definition: cmdata.h:93
Definition: dlist.c:348
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define REG_SZ
Definition: layer.c:22