ReactOS 0.4.15-dev-7994-gb388cb6
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.
 
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.
 
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.
 
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.
 
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.
 
static BOOLEAN CmpDoSort (_Inout_ PLIST_ENTRY DriverListHead, _In_ PCUNICODE_STRING OrderList)
 Performs the driver list sorting, according to the ordering list.
 
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.
 
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.
 
VOID NTAPI CmpFreeDriverList (_In_ PHHIVE Hive, _Inout_ PLIST_ENTRY DriverListHead)
 Empties the driver list and frees all allocated driver nodes in it.
 

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;
376 USHORT NameLength;
377 HCELL_INDEX ValueCell, TagCell;
378 PUNICODE_STRING FilePath, RegistryString;
380 PULONG ErrorControl;
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 */
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 */
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 */
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 */
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
577Failure:
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}
PCWSTR FilePath
struct NameRec_ * Name
Definition: cdprocs.h:460
Definition: bufpool.h:45
#define CMTRACE(x, fmt,...)
Definition: cm.h:40
#define CM_BOOT_DEBUG
Definition: cmboot.c:39
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
#define IS_NULL_TERMINATED(Buffer, Size)
Definition: cmboot.c:41
struct _CM_KEY_NODE * PCM_KEY_NODE
#define KEY_COMP_NAME
Definition: cmdata.h:35
struct _CM_KEY_VALUE * PCM_KEY_VALUE
VOID NTAPI CmpCopyCompressedName(OUT PWCHAR Destination, IN ULONG DestinationLength, IN PWCHAR Source, IN ULONG SourceLength)
Definition: cmname.c:56
HCELL_INDEX NTAPI CmpFindValueByName(IN PHHIVE Hive, IN PCM_KEY_NODE KeyNode, IN PCUNICODE_STRING Name)
Definition: cmvalue.c:99
PCELL_DATA NTAPI CmpValueToData(IN PHHIVE Hive, IN PCM_KEY_VALUE Value, OUT PULONG Length)
Definition: cmvalue.c:167
USHORT NTAPI CmpCompressedNameSize(IN PWCHAR Name, IN ULONG Length)
Definition: cmname.c:95
#define HvGetCell(Hive, Cell)
Definition: cmlib.h:457
#define TAG_CM
Definition: cmlib.h:212
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
union node Node
Definition: types.h:1255
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
#define InsertHeadList(ListHead, Entry)
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define HCELL_NIL
Definition: hivedata.h:110
ULONG HCELL_INDEX
Definition: hivedata.h:105
#define REG_SZ
Definition: layer.c:22
#define ASSERT(a)
Definition: mode.c:44
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
#define REG_DWORD
Definition: sdbapi.c:596
Definition: arc.h:246
UNICODE_STRING Group
Definition: cmboot.h:16
BOOT_DRIVER_LIST_ENTRY ListEntry
Definition: cmboot.h:15
ULONG ErrorControl
Definition: cmboot.h:19
UNICODE_STRING Name
Definition: cmboot.h:17
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
Definition: dlist.c:348
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
@ NormalError
Definition: cmtypes.h:1005
__wchar_t WCHAR
Definition: xmlstorage.h:180

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}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
LIST_ENTRY Link
Definition: arc.h:247
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

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;
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");
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 */
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}
LONG NTSTATUS
Definition: precomp.h:26
PHHIVE SystemHive
Definition: registry.c:33
HCELL_INDEX NTAPI CmpFindSubKeyByName(IN PHHIVE Hive, IN PCM_KEY_NODE Parent, IN PCUNICODE_STRING SearchName)
Definition: cmindex.c:683
Status
Definition: gdiplustypes.h:25
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
PRELEASE_CELL_ROUTINE ReleaseCellRoutine
Definition: hivedata.h:317
unsigned char * PBOOLEAN
Definition: typedefs.h:53

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 */
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}
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
static BOOLEAN CmpIsSafe(_In_ PHHIVE Hive, _In_ HCELL_INDEX SafeBootCell, _In_ HCELL_INDEX DriverCell)
Definition: cmboot.c:1081
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
ULONG InitSafeBootMode
Definition: init.c:71
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
Definition: cmindex.c:600
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
PCWSTR BootFileSystem
Definition: winldr.c:30
#define SERVICE_ERROR_CRITICAL
Definition: cmtypes.h:984

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}
unsigned char BOOLEAN
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

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,
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}
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
base of all file and directory entries
Definition: entries.h:83
UNICODE_STRING RegistryPath
Definition: arc.h:249
UNICODE_STRING FilePath
Definition: arc.h:248

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;
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;
644 if (!Data) return FALSE;
645 if (Length < sizeof(ULONG)) return FALSE;
646
647 /* Return if the type matches */
648 return (*Data == LoadType);
649}
#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 */
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 OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
#define wcsrchr
Definition: compat.h:16
#define ULONG_PTR
Definition: config.h:101
WCHAR Name[ANYSIZE_ARRAY]
Definition: cmdata.h:116
USHORT NameLength
Definition: cmdata.h:114
USHORT Flags
Definition: cmdata.h:93
ULONG Type
Definition: cmdata.h:128
uint32_t ULONG_PTR
Definition: typedefs.h:65

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}
#define InsertTailList(ListHead, Entry)
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122

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}
static BOOLEAN CmpOrderGroup(_In_ PBOOT_DRIVER_NODE StartNode, _In_ PBOOT_DRIVER_NODE EndNode)
Definition: cmboot.c:956

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;
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}
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
#define REG_MULTI_SZ
Definition: nt_native.h:1501

Referenced by CmGetSystemDriverList(), and WinLdrScanRegistry().

Variable Documentation

◆ InitSafeBootMode

ULONG InitSafeBootMode
extern

Definition at line 71 of file init.c.

Referenced by CmpFindDrivers().