ReactOS  0.4.15-dev-5446-g3f3714b
cmboot.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for cmboot.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define CM_BOOT_DEBUG   0x20
 
#define IS_NULL_TERMINATED(Buffer, Size)   (((Size) >= sizeof(WCHAR)) && ((Buffer)[(Size) / sizeof(WCHAR) - 1] == UNICODE_NULL))
 

Functions

static BOOLEAN CmpIsSafe (_In_ PHHIVE Hive, _In_ HCELL_INDEX SafeBootCell, _In_ HCELL_INDEX DriverCell)
 
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, according to the "Current", "Default", or "LastKnownGood" values in the "HKLM\SYSTEM\Select" registry key. More...
 
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. More...
 
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. More...
 
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. More...
 
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, and inserts them into the driver list. More...
 
static BOOLEAN CmpDoSort (_Inout_ PLIST_ENTRY DriverListHead, _In_ PCUNICODE_STRING OrderList)
 Performs the driver list sorting, according to the ordering list. More...
 
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. More...
 
static BOOLEAN CmpOrderGroup (_In_ PBOOT_DRIVER_NODE StartNode, _In_ PBOOT_DRIVER_NODE EndNode)
 
BOOLEAN NTAPI CmpResolveDriverDependencies (_Inout_ PLIST_ENTRY DriverListHead)
 Removes potential circular dependencies (cycles) and sorts the driver list. More...
 
VOID NTAPI CmpFreeDriverList (_In_ PHHIVE Hive, _Inout_ PLIST_ENTRY DriverListHead)
 Empties the driver list and frees all allocated driver nodes in it. More...
 

Variables

ULONG InitSafeBootMode
 

Macro Definition Documentation

◆ CM_BOOT_DEBUG

#define CM_BOOT_DEBUG   0x20

Definition at line 39 of file cmboot.c.

◆ IS_NULL_TERMINATED

#define IS_NULL_TERMINATED (   Buffer,
  Size 
)    (((Size) >= sizeof(WCHAR)) && ((Buffer)[(Size) / sizeof(WCHAR) - 1] == UNICODE_NULL))

Definition at line 41 of file cmboot.c.

◆ NDEBUG

#define NDEBUG

Definition at line 16 of file cmboot.c.

Function Documentation

◆ CmpAddDriverToList()

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.

Parameters
[in]HiveThe SYSTEM hive.
[in]DriverCellThe registry key's hive cell of the driver to be added, inside the "Services" sub-key of the currently selected control set.
[in]GroupOrderCellThe hive cell of the "Control\GroupOrderList" registry key inside the currently selected control set.
[in]RegistryPathConstant UNICODE_STRING pointing to "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\".
[in,out]DriverListHeadThe driver list where to insert the driver entry.
Returns
TRUE if the driver has been inserted into the list, FALSE if not.

Definition at line 364 of file cmboot.c.

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 }
#define KEY_COMP_NAME
Definition: cmdata.h:35
#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
USHORT MaximumLength
Definition: env_spec_w32.h:370
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define TRUE
Definition: types.h:120
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_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:213
#define HCELL_NIL
Definition: hivedata.h:85
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CM_BOOT_DEBUG
Definition: cmboot.c:39
PCWSTR FilePath
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:381
Definition: arc.h:198
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
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
struct NameRec_ * Name
Definition: cdprocs.h:459
struct _CM_KEY_NODE * PCM_KEY_NODE
Definition: bufpool.h:45
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
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
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
#define TAG_CM
Definition: cmlib.h:205
UNICODE_STRING Group
Definition: cmboot.h:16
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
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
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
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 RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IS_NULL_TERMINATED(Buffer, Size)
Definition: cmboot.c:41
#define REG_DWORD
Definition: sdbapi.c:596
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
Definition: dlist.c:348
#define REG_SZ
Definition: layer.c:22

Referenced by CmpFindDrivers().

◆ CmpDoSort()

static BOOLEAN CmpDoSort ( _Inout_ PLIST_ENTRY  DriverListHead,
_In_ PCUNICODE_STRING  OrderList 
)
static

Performs the driver list sorting, according to the ordering list.

Parameters
[in]HiveThe SYSTEM hive.
[in]ControlSetThe control set registry key's hive cell.
[in,out]DriverListHeadThe driver list to sort.
Returns
TRUE if sorting has been successfully done, FALSE if not.

Definition at line 828 of file cmboot.c.

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 }
BOOT_DRIVER_LIST_ENTRY ListEntry
Definition: cmboot.h:15
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define TRUE
Definition: types.h:120
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
uint16_t * PWCHAR
Definition: typedefs.h:56
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define UNICODE_NULL
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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
Definition: typedefs.h:119
UNICODE_STRING Group
Definition: cmboot.h:16
unsigned short USHORT
Definition: pedump.c:61
#define NULL
Definition: types.h:112
LIST_ENTRY Link
Definition: arc.h:200
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)

Referenced by CmpSortDriverList().

◆ CmpFindControlSet()

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, according to the "Current", "Default", or "LastKnownGood" values in the "HKLM\SYSTEM\Select" registry key.

Parameters
[in]SystemHiveThe SYSTEM hive.
[in]RootCellThe root cell of the SYSTEM hive.
[in]SelectKeyNameThe control set to check for: either "Current", "Default", or "LastKnownGood", the value of which selects the corresponding "HKLM\SYSTEM\ControlSetXXX" control set registry key.
[out]AutoSelectValue of the "AutoSelect" registry value (unused).
Returns
The control set registry key's hive cell (if found), or HCELL_NIL.

Definition at line 84 of file cmboot.c.

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 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
#define HCELL_NIL
Definition: hivedata.h:85
PHHIVE SystemHive
Definition: registry.c:32
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:381
#define L(x)
Definition: ntvdm.h:50
union node Node
Definition: types.h:1255
struct NameRec_ * Name
Definition: cdprocs.h:459
struct _CM_KEY_NODE * PCM_KEY_NODE
Definition: bufpool.h:45
_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
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
#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
ULONG HCELL_INDEX
Definition: hivedata.h:80
char * PBOOLEAN
Definition: retypes.h:11
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
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#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
PRELEASE_CELL_ROUTINE ReleaseCellRoutine
Definition: hivedata.h:292
Definition: dlist.c:348

Referenced by CmGetSystemControlValues(), CmGetSystemDriverList(), and RegInitCurrentControlSet().

◆ CmpFindDrivers()

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, and inserts them into the driver list.

Parameters
[in]HiveThe SYSTEM hive.
[in]ControlSetThe control set registry key's hive cell.
[in]LoadTypeThe load type the driver should match.
[in]BootFileSystemOptional name of the boot file system, for which to insert its corresponding driver.
[in,out]DriverListHeadThe driver list where to insert the enumerated drivers.
Returns
TRUE if the drivers have been successfully enumerated and inserted, FALSE if not.

Definition at line 679 of file cmboot.c.

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 }
#define CMTRACE(x, fmt,...)
Definition: cm.h:40
#define TRUE
Definition: types.h:120
ULONG ErrorControl
Definition: cmboot.h:19
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
Definition: cmindex.c:600
#define HCELL_NIL
Definition: hivedata.h:85
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
#define CM_BOOT_DEBUG
Definition: cmboot.c:39
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:381
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
#define FALSE
Definition: types.h:117
union node Node
Definition: types.h:1255
struct NameRec_ * Name
Definition: cdprocs.h:459
struct _CM_KEY_NODE * PCM_KEY_NODE
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
#define ASSERT(a)
Definition: mode.c:44
ULONG HCELL_INDEX
Definition: hivedata.h:80
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
#define NULL
Definition: types.h:112
ULONG InitSafeBootMode
Definition: init.c:71
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define SERVICE_ERROR_CRITICAL
Definition: cmtypes.h:984
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
Definition: dlist.c:348

Referenced by CmGetSystemDriverList(), and WinLdrScanRegistry().

◆ CmpFindTagIndex()

static ULONG CmpFindTagIndex ( _In_ PHHIVE  Hive,
_In_ HCELL_INDEX  TagCell,
_In_ HCELL_INDEX  GroupOrderCell,
_In_ PCUNICODE_STRING  GroupName 
)
static

Finds the index of the driver's "Tag" value in its corresponding group ordering list.

Parameters
[in]HiveThe SYSTEM hive.
[in]TagCellThe driver's "Tag" registry value's hive cell.
[in]GroupOrderCellThe hive cell of the "Control\GroupOrderList" registry key inside the currently selected control set.
[in]GroupNameThe driver's group name.
Returns
The corresponding tag index, or -1 (last position), or -2 (next-to-last position).

Definition at line 215 of file cmboot.c.

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 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
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
#define HCELL_NIL
Definition: hivedata.h:85
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:381
union node Node
Definition: types.h:1255
unsigned char BOOLEAN
struct _CM_KEY_NODE * PCM_KEY_NODE
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
#define ASSERT(a)
Definition: mode.c:44
ULONG HCELL_INDEX
Definition: hivedata.h:80
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
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define REG_DWORD
Definition: sdbapi.c:596
Definition: dlist.c:348

Referenced by CmpAddDriverToList().

◆ CmpFreeDriverList()

VOID NTAPI CmpFreeDriverList ( _In_ PHHIVE  Hive,
_Inout_ PLIST_ENTRY  DriverListHead 
)

Empties the driver list and frees all allocated driver nodes in it.

Parameters
[in]HiveThe SYSTEM hive (used only for the Hive->Free() memory deallocator).
[in,out]DriverListHeadThe driver list to free.
Returns
None

Definition at line 1224 of file cmboot.c.

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 }
BOOT_DRIVER_LIST_ENTRY ListEntry
Definition: cmboot.h:15
struct _Entry Entry
Definition: kefuncs.h:629
USHORT MaximumLength
Definition: env_spec_w32.h:370
UNICODE_STRING FilePath
Definition: arc.h:201
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
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
UNICODE_STRING Name
Definition: cmboot.h:17
Definition: typedefs.h:119
UNICODE_STRING RegistryPath
Definition: arc.h:202
base of all file and directory entries
Definition: entries.h:82

Referenced by CmGetSystemDriverList(), and WinLdrScanRegistry().

◆ CmpIsLoadType()

static BOOLEAN CmpIsLoadType ( _In_ PHHIVE  Hive,
_In_ HCELL_INDEX  Cell,
_In_ SERVICE_LOAD_TYPE  LoadType 
)
static

Checks whether the specified driver has the expected load type.

Parameters
[in]HiveThe SYSTEM hive.
[in]DriverCellThe registry key's hive cell of the driver, inside the "Services" sub-key of the currently selected control set.
[in]LoadTypeThe load type the driver should match.
Returns
TRUE if the driver's load type matches, FALSE if not.

Definition at line 618 of file cmboot.c.

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 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG _In_opt_ PVOID Data
Definition: wdfdevice.h:4527
#define HCELL_NIL
Definition: hivedata.h:85
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:381
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
union node Node
Definition: types.h:1255
struct _CM_KEY_NODE * PCM_KEY_NODE
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
#define ASSERT(a)
Definition: mode.c:44
ULONG HCELL_INDEX
Definition: hivedata.h:80
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
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
#define REG_DWORD
Definition: sdbapi.c:596
Definition: dlist.c:348
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14

Referenced by CmpFindDrivers().

◆ CmpIsSafe()

static BOOLEAN CmpIsSafe ( _In_ PHHIVE  Hive,
_In_ HCELL_INDEX  SafeBootCell,
_In_ HCELL_INDEX  DriverCell 
)
static

Definition at line 1081 of file cmboot.c.

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 }
#define KEY_COMP_NAME
Definition: cmdata.h:35
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define TRUE
Definition: types.h:120
#define HCELL_NIL
Definition: hivedata.h:85
uint16_t * PWCHAR
Definition: typedefs.h:56
USHORT NameLength
Definition: cmdata.h:114
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:381
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
struct NameRec_ * Name
Definition: cdprocs.h:459
struct _CM_KEY_NODE * PCM_KEY_NODE
Definition: bufpool.h:45
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
ULONG HCELL_INDEX
Definition: hivedata.h:80
#define TAG_CM
Definition: cmlib.h:205
#define wcsrchr
Definition: compat.h:16
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
#define NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IS_NULL_TERMINATED(Buffer, Size)
Definition: cmboot.c:41
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
USHORT Flags
Definition: cmdata.h:93
#define REG_SZ
Definition: layer.c:22

Referenced by CmpFindDrivers().

◆ CmpOrderGroup()

static BOOLEAN CmpOrderGroup ( _In_ PBOOT_DRIVER_NODE  StartNode,
_In_ PBOOT_DRIVER_NODE  EndNode 
)
static

Definition at line 956 of file cmboot.c.

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 }
BOOT_DRIVER_LIST_ENTRY ListEntry
Definition: cmboot.h:15
#define TRUE
Definition: types.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
#define InsertTailList(ListHead, Entry)
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: typedefs.h:119
LIST_ENTRY Link
Definition: arc.h:200

Referenced by CmpResolveDriverDependencies().

◆ CmpResolveDriverDependencies()

BOOLEAN NTAPI CmpResolveDriverDependencies ( _Inout_ PLIST_ENTRY  DriverListHead)

Removes potential circular dependencies (cycles) and sorts the driver list.

Parameters
[in,out]DriverListHeadThe driver list to sort.
Returns
Always TRUE.

Definition at line 1030 of file cmboot.c.

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 }
#define TRUE
Definition: types.h:120
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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
static BOOLEAN CmpOrderGroup(_In_ PBOOT_DRIVER_NODE StartNode, _In_ PBOOT_DRIVER_NODE EndNode)
Definition: cmboot.c:956
Definition: typedefs.h:119
UNICODE_STRING Group
Definition: cmboot.h:16
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)

Referenced by CmGetSystemDriverList(), and WinLdrScanRegistry().

◆ CmpSortDriverList()

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.

Parameters
[in]HiveThe SYSTEM hive.
[in]ControlSetThe control set registry key's hive cell.
[in,out]DriverListHeadThe driver list to sort.
Returns
TRUE if sorting has been successfully done, FALSE if not.

Definition at line 902 of file cmboot.c.

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 }
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define HCELL_NIL
Definition: hivedata.h:85
uint16_t * PWCHAR
Definition: typedefs.h:56
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:381
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
union node Node
Definition: types.h:1255
#define REG_MULTI_SZ
Definition: nt_native.h:1501
struct NameRec_ * Name
Definition: cdprocs.h:459
struct _CM_KEY_NODE * PCM_KEY_NODE
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
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
#define ASSERT(a)
Definition: mode.c:44
ULONG HCELL_INDEX
Definition: hivedata.h:80
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 NULL
Definition: types.h:112
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define IS_NULL_TERMINATED(Buffer, Size)
Definition: cmboot.c:41
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
Definition: dlist.c:348

Referenced by CmGetSystemDriverList(), and WinLdrScanRegistry().

Variable Documentation

◆ InitSafeBootMode

ULONG InitSafeBootMode

Definition at line 71 of file init.c.

Referenced by CmpFindDrivers().