ReactOS 0.4.17-dev-1196-gb6224c3
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.
 

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 362 of file cmboot.c.

368{
369 PBOOT_DRIVER_NODE DriverNode;
374 USHORT NameLength;
375 HCELL_INDEX ValueCell, TagCell;
376 PUNICODE_STRING FilePath, RegistryString;
378 PULONG ErrorControl;
380
381 /* Sanity check: We shouldn't need to release any acquired cells */
382 ASSERT(Hive->ReleaseCellRoutine == NULL);
383
384 /* Allocate a driver node and initialize it */
385 DriverNode = Hive->Allocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM);
386 if (!DriverNode)
387 return FALSE;
388
389 RtlZeroMemory(DriverNode, sizeof(BOOT_DRIVER_NODE));
390 DriverEntry = &DriverNode->ListEntry;
391
392 /* Get the driver cell */
393 Node = (PCM_KEY_NODE)HvGetCell(Hive, DriverCell);
394 if (!Node)
395 goto Failure;
396
397 /* Get the name from the cell */
398 NameLength = (Node->Flags & KEY_COMP_NAME) ?
399 CmpCompressedNameSize(Node->Name, Node->NameLength) :
400 Node->NameLength;
401 if (NameLength < sizeof(WCHAR))
402 goto Failure;
403
404 /* Now allocate the buffer for it and copy the name */
405 RtlInitEmptyUnicodeString(&DriverNode->Name,
406 Hive->Allocate(NameLength, FALSE, TAG_CM),
407 NameLength);
408 if (!DriverNode->Name.Buffer)
409 goto Failure;
410
411 DriverNode->Name.Length = NameLength;
412 if (Node->Flags & KEY_COMP_NAME)
413 {
414 /* Compressed name */
416 DriverNode->Name.Length,
417 Node->Name,
418 Node->NameLength);
419 }
420 else
421 {
422 /* Normal name */
423 RtlCopyMemory(DriverNode->Name.Buffer, Node->Name, Node->NameLength);
424 }
425
426 /* Now find the image path */
427 RtlInitUnicodeString(&Name, L"ImagePath");
428 ValueCell = CmpFindValueByName(Hive, Node, &Name);
429 if (ValueCell == HCELL_NIL)
430 {
431 /* Could not find it, so assume the drivers path */
432 Length = sizeof(L"System32\\Drivers\\") + NameLength + sizeof(L".sys");
433
434 /* Allocate the path name */
435 FilePath = &DriverEntry->FilePath;
436 RtlInitEmptyUnicodeString(FilePath,
437 Hive->Allocate(Length, FALSE, TAG_CM),
438 (USHORT)Length);
439 if (!FilePath->Buffer)
440 goto Failure;
441
442 /* Write the path name */
443 if (!NT_SUCCESS(RtlAppendUnicodeToString(FilePath, L"System32\\Drivers\\")) ||
446 {
447 goto Failure;
448 }
449 }
450 else
451 {
452 /* Path name exists, so grab it */
453 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
454 if (!Value)
455 goto Failure;
456 if ((Value->Type != REG_SZ) && (Value->Type != REG_EXPAND_SZ))
457 goto Failure;
459 if (!Buffer)
460 goto Failure;
462 Length -= sizeof(UNICODE_NULL);
463 if (Length < sizeof(WCHAR))
464 goto Failure;
465
466 /* Allocate and setup the path name */
467 FilePath = &DriverEntry->FilePath;
468 RtlInitEmptyUnicodeString(FilePath,
469 Hive->Allocate(Length, FALSE, TAG_CM),
470 (USHORT)Length);
471 if (!FilePath->Buffer)
472 goto Failure;
473
474 /* Transfer the data */
476 FilePath->Length = (USHORT)Length;
477 }
478
479 /* Now build the registry path */
480 RegistryString = &DriverEntry->RegistryPath;
481 Length = RegistryPath->Length + NameLength;
482 RtlInitEmptyUnicodeString(RegistryString,
483 Hive->Allocate(Length, FALSE, TAG_CM),
484 (USHORT)Length);
485 if (!RegistryString->Buffer)
486 goto Failure;
487
488 /* Add the driver name to it */
490 !NT_SUCCESS(RtlAppendUnicodeStringToString(RegistryString, &DriverNode->Name)))
491 {
492 goto Failure;
493 }
494
495 /* The entry is done, add it */
496 InsertHeadList(DriverListHead, &DriverEntry->Link);
497
498 /* Now find error control settings */
499 RtlInitUnicodeString(&Name, L"ErrorControl");
500 ValueCell = CmpFindValueByName(Hive, Node, &Name);
501 if (ValueCell == HCELL_NIL)
502 {
503 /* Could not find it, so assume default */
504 DriverNode->ErrorControl = NormalError;
505 }
506 else
507 {
508 /* Otherwise, read whatever the data says */
509 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
510 if (!Value)
511 goto Failure;
512 if (Value->Type != REG_DWORD)
513 goto Failure;
514 ErrorControl = (PULONG)CmpValueToData(Hive, Value, &Length);
515 if (!ErrorControl)
516 goto Failure;
517 if (Length < sizeof(ULONG))
518 goto Failure;
519
520 DriverNode->ErrorControl = *ErrorControl;
521 }
522
523 /* Next, get the group cell */
524 RtlInitUnicodeString(&Name, L"group");
525 ValueCell = CmpFindValueByName(Hive, Node, &Name);
526 if (ValueCell == HCELL_NIL)
527 {
528 /* Could not find it, so set an empty string */
529 RtlInitEmptyUnicodeString(&DriverNode->Group, NULL, 0);
530 }
531 else
532 {
533 /* Found it, read the group value */
534 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
535 if (!Value)
536 goto Failure;
537 if (Value->Type != REG_SZ) // REG_EXPAND_SZ not really allowed there.
538 goto Failure;
539
540 /* Copy it into the node */
542 if (!Buffer)
543 goto Failure;
545 Length -= sizeof(UNICODE_NULL);
546
547 DriverNode->Group.Buffer = Buffer;
548 DriverNode->Group.Length = (USHORT)Length;
549 DriverNode->Group.MaximumLength = DriverNode->Group.Length;
550 }
551
552 /* Finally, find the tag */
554 TagCell = CmpFindValueByName(Hive, Node, &Name);
555 if (TagCell == HCELL_NIL)
556 {
557 /* No tag, so load last */
558 DriverNode->Tag = -1;
559 }
560 else
561 {
562 /* Otherwise, decode it based on tag order */
563 DriverNode->Tag = CmpFindTagIndex(Hive,
564 TagCell,
565 GroupOrderCell,
566 &DriverNode->Group);
567 }
568
569 CMTRACE(CM_BOOT_DEBUG, "Adding boot driver: '%wZ', '%wZ'\n",
570 &DriverNode->Name, &DriverEntry->FilePath);
571
572 /* All done! */
573 return TRUE;
574
575Failure:
576 if (DriverEntry->RegistryPath.Buffer)
577 {
578 Hive->Free(DriverEntry->RegistryPath.Buffer,
579 DriverEntry->RegistryPath.MaximumLength);
580 }
581 if (DriverEntry->FilePath.Buffer)
582 {
583 Hive->Free(DriverEntry->FilePath.Buffer,
584 DriverEntry->FilePath.MaximumLength);
585 }
586 if (DriverNode->Name.Buffer)
587 {
588 Hive->Free(DriverNode->Name.Buffer,
589 DriverNode->Name.MaximumLength);
590 }
591 Hive->Free(DriverNode, sizeof(BOOT_DRIVER_NODE));
592
593 return FALSE;
594}
PCWSTR FilePath
#define REG_SZ
Definition: layer.c:22
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:213
#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:473
#define TAG_CM
Definition: cmlib.h:219
LPWSTR Name
Definition: desk.c:124
#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:33
union node Node
Definition: types.h:1255
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
#define L(x)
Definition: resources.c:13
#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 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:1497
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
short WCHAR
Definition: pedump.c:58
unsigned short USHORT
Definition: pedump.c:61
#define REG_DWORD
Definition: sdbapi.c:615
Definition: arc.h:334
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:1006

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 826 of file cmboot.c.

829{
830 PWCHAR Current, End = NULL;
831 UNICODE_STRING GroupName;
832 PLIST_ENTRY NextEntry;
833 PBOOT_DRIVER_NODE CurrentNode;
834
835 /* We're going from end to start, so get to the last group and keep going */
836 Current = &OrderList->Buffer[OrderList->Length / sizeof(WCHAR)];
837 while (Current > OrderList->Buffer)
838 {
839 /* Scan the current string */
840 do
841 {
842 if (*Current == UNICODE_NULL) End = Current;
843 } while ((*(--Current - 1) != UNICODE_NULL) && (Current != OrderList->Buffer));
844
845 /* This is our cleaned up string for this specific group */
846 ASSERT(End != NULL);
847 GroupName.Length = (USHORT)(End - Current) * sizeof(WCHAR);
848 GroupName.MaximumLength = GroupName.Length;
849 GroupName.Buffer = Current;
850
851 /* Now loop the driver list */
852 NextEntry = DriverListHead->Flink;
853 while (NextEntry != DriverListHead)
854 {
855 /* Get this node */
856 CurrentNode = CONTAINING_RECORD(NextEntry,
858 ListEntry.Link);
859
860 /* Get the next entry now since we'll do a relink */
861 NextEntry = NextEntry->Flink;
862
863 /* Is there a group name and does it match the current group? */
864 if (CurrentNode->Group.Buffer &&
865 RtlEqualUnicodeString(&GroupName, &CurrentNode->Group, TRUE))
866 {
867 /* Remove from this location and re-link in the new one */
868 RemoveEntryList(&CurrentNode->ListEntry.Link);
869 InsertHeadList(DriverListHead, &CurrentNode->ListEntry.Link);
870 }
871 }
872
873 /* Move on */
874 --Current;
875 }
876
877 /* All done */
878 return TRUE;
879}
#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:335
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 82 of file cmboot.c.

87{
90 HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
91 HCELL_INDEX CurrentValueCell;
95 PULONG CurrentData;
96 PULONG ControlSetId;
97 WCHAR Buffer[128];
98
99 /* Sanity check: We shouldn't need to release any acquired cells */
101
102 /* Get the Select key */
103 RtlInitUnicodeString(&Name, L"select");
105 if (!Node) return HCELL_NIL;
106 SelectCell = CmpFindSubKeyByName(SystemHive, Node, &Name);
107 if (SelectCell == HCELL_NIL) return HCELL_NIL;
108
109 /* Get AutoSelect value */
110 RtlInitUnicodeString(&Name, L"AutoSelect");
111 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
112 if (!Node) return HCELL_NIL;
113 AutoSelectCell = CmpFindValueByName(SystemHive, Node, &Name);
114 if (AutoSelectCell == HCELL_NIL)
115 {
116 /* Assume TRUE if the value is missing */
117 *AutoSelect = TRUE;
118 }
119 else
120 {
121 /* Read the value */
122 Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
123 if (!Value) return HCELL_NIL;
124 // if (Value->Type != REG_DWORD) return HCELL_NIL;
125
126 /* Convert it to a boolean */
127 CurrentData = (PULONG)CmpValueToData(SystemHive, Value, &Length);
128 if (!CurrentData) return HCELL_NIL;
129 // if (Length < sizeof(ULONG)) return HCELL_NIL;
130
131 *AutoSelect = *(PBOOLEAN)CurrentData;
132 }
133
134 /* Now find the control set being looked up */
135 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
136 if (!Node) return HCELL_NIL;
137 SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
138 if (SelectValueCell == HCELL_NIL) return HCELL_NIL;
139
140 /* Read the value (corresponding to the CCS ID) */
141 Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
142 if (!Value) return HCELL_NIL;
143 if (Value->Type != REG_DWORD) return HCELL_NIL;
144 ControlSetId = (PULONG)CmpValueToData(SystemHive, Value, &Length);
145 if (!ControlSetId) return HCELL_NIL;
146 if (Length < sizeof(ULONG)) return HCELL_NIL;
147
148 /* Now build the CCS's Name */
150 L"ControlSet%03lu", *ControlSetId);
151 if (!NT_SUCCESS(Status)) return HCELL_NIL;
152 /* RtlStringCbPrintfW ensures the buffer to be NULL-terminated */
154
155 /* Now open it */
157 if (!Node) return HCELL_NIL;
158 ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &Name);
159 if (ControlSetCell == HCELL_NIL) return HCELL_NIL;
160
161 /* Get the value of the "Current" CCS */
162 RtlInitUnicodeString(&Name, L"Current");
163 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
164 if (!Node) return HCELL_NIL;
165 CurrentValueCell = CmpFindValueByName(SystemHive, Node, &Name);
166
167 /* Make sure it exists */
168 if (CurrentValueCell != HCELL_NIL)
169 {
170 /* Get the current value and make sure it's a ULONG */
171 Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
172 if (!Value) return HCELL_NIL;
173 if (Value->Type == REG_DWORD)
174 {
175 /* Get the data and update it */
176 CurrentData = (PULONG)CmpValueToData(SystemHive, Value, &Length);
177 if (!CurrentData) return HCELL_NIL;
178 if (Length < sizeof(ULONG)) return HCELL_NIL;
179
180 *CurrentData = *ControlSetId;
181 }
182 }
183
184 /* Return the CCS cell */
185 return ControlSetCell;
186}
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:24
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 677 of file cmboot.c.

683{
684 HCELL_INDEX ServicesCell, ControlCell, GroupOrderCell, DriverCell;
685 HCELL_INDEX SafeBootCell = HCELL_NIL;
686 ULONG i;
688 UNICODE_STRING KeyPath;
689 PCM_KEY_NODE ControlNode, ServicesNode, Node;
690 PBOOT_DRIVER_NODE FsNode;
691
692 /* Sanity check: We shouldn't need to release any acquired cells */
693 ASSERT(Hive->ReleaseCellRoutine == NULL);
694
695 /* Open the control set key */
696 ControlNode = (PCM_KEY_NODE)HvGetCell(Hive, ControlSet);
697 if (!ControlNode) return FALSE;
698
699 /* Get services cell */
700 RtlInitUnicodeString(&Name, L"Services");
701 ServicesCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
702 if (ServicesCell == HCELL_NIL) return FALSE;
703
704 /* Open services key */
705 ServicesNode = (PCM_KEY_NODE)HvGetCell(Hive, ServicesCell);
706 if (!ServicesNode) return FALSE;
707
708 /* Get control cell */
709 RtlInitUnicodeString(&Name, L"Control");
710 ControlCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
711 if (ControlCell == HCELL_NIL) return FALSE;
712
713 /* Get the group order cell and read it */
714 Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlCell);
715 if (!Node) return FALSE;
716 RtlInitUnicodeString(&Name, L"GroupOrderList");
717 GroupOrderCell = CmpFindSubKeyByName(Hive, Node, &Name);
718 if (GroupOrderCell == HCELL_NIL) return FALSE;
719
720 /* Get Safe Boot cell */
722 {
723 /* Open the Safe Boot key */
724 RtlInitUnicodeString(&Name, L"SafeBoot");
725 Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlCell);
726 if (!Node) return FALSE;
727 SafeBootCell = CmpFindSubKeyByName(Hive, Node, &Name);
728 if (SafeBootCell == HCELL_NIL) return FALSE;
729
730 /* Open the correct start key (depending on the mode) */
731 Node = (PCM_KEY_NODE)HvGetCell(Hive, SafeBootCell);
732 if (!Node) return FALSE;
733 switch (InitSafeBootMode)
734 {
735 /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
736 case 1:
737 case 3: RtlInitUnicodeString(&Name, L"Minimal"); break;
738 case 2: RtlInitUnicodeString(&Name, L"Network"); break;
739 default: return FALSE;
740 }
741 SafeBootCell = CmpFindSubKeyByName(Hive, Node, &Name);
742 if (SafeBootCell == HCELL_NIL) return FALSE;
743 }
744
745 /* Build the root registry path */
746 RtlInitUnicodeString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
747
748 /* Enumerate each sub-key */
749 i = 0;
750 DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, i);
751 while (DriverCell != HCELL_NIL)
752 {
753 /* Make sure it's a driver of this start type AND is "safe" to load */
754 if (CmpIsLoadType(Hive, DriverCell, LoadType) &&
755 CmpIsSafe(Hive, SafeBootCell, DriverCell))
756 {
757 /* Add it to the list */
758 if (!CmpAddDriverToList(Hive,
759 DriverCell,
760 GroupOrderCell,
761 &KeyPath,
762 DriverListHead))
763 {
764 CMTRACE(CM_BOOT_DEBUG, " Failed to add boot driver\n");
765 }
766 }
767
768 /* Go to the next sub-key */
769 DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, ++i);
770 }
771
772 /* Check if we have a boot file system */
773 if (BootFileSystem)
774 {
775 /* Find it */
777 DriverCell = CmpFindSubKeyByName(Hive, ServicesNode, &Name);
778 if (DriverCell != HCELL_NIL)
779 {
780 CMTRACE(CM_BOOT_DEBUG, "Adding Boot FileSystem '%S'\n",
782
783 /* Always add it to the list */
784 if (!CmpAddDriverToList(Hive,
785 DriverCell,
786 GroupOrderCell,
787 &KeyPath,
788 DriverListHead))
789 {
790 CMTRACE(CM_BOOT_DEBUG, " Failed to add boot driver\n");
791 }
792 else
793 {
794 /* Mark it as critical so it always loads */
795 FsNode = CONTAINING_RECORD(DriverListHead->Flink,
797 ListEntry.Link);
799 }
800 }
801 }
802
803 /* We're done! */
804 return TRUE;
805}
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:616
static BOOLEAN CmpIsSafe(_In_ PHHIVE Hive, _In_ HCELL_INDEX SafeBootCell, _In_ HCELL_INDEX DriverCell)
Definition: cmboot.c:1079
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:362
HCELL_INDEX NTAPI CmpFindSubKeyByNumber(IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN ULONG Number)
Definition: cmindex.c:600
PULONG InitSafeBootMode
Definition: init.c:75
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:31
#define SERVICE_ERROR_CRITICAL
Definition: cmtypes.h:985

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 213 of file cmboot.c.

218{
219 PCM_KEY_VALUE TagValue, Value;
221 HCELL_INDEX OrderCell;
222 PULONG DriverTag, TagOrder;
223 ULONG CurrentTag, Length;
224 BOOLEAN BufferAllocated;
225
226 /* Sanity check: We shouldn't need to release any acquired cells */
227 ASSERT(Hive->ReleaseCellRoutine == NULL);
228
229 /* Get the tag */
230 Value = (PCM_KEY_VALUE)HvGetCell(Hive, TagCell);
231 if (!Value) return -2;
232 if (Value->Type != REG_DWORD) return -2;
233 DriverTag = (PULONG)CmpValueToData(Hive, Value, &Length);
234 if (!DriverTag) return -2;
235 if (Length < sizeof(ULONG)) return -2;
236
237 /* Get the order array */
238 Node = (PCM_KEY_NODE)HvGetCell(Hive, GroupOrderCell);
239 if (!Node) return -2;
240 OrderCell = CmpFindValueByName(Hive, Node, GroupName);
241 if (OrderCell == HCELL_NIL) return -2;
242
243 /* And read it */
244 TagValue = (PCM_KEY_VALUE)HvGetCell(Hive, OrderCell);
245 if (!TagValue) return -2;
246 if (!CmpGetValueData(Hive,
247 TagValue,
248 &Length,
249 (PVOID*)&TagOrder,
250 &BufferAllocated,
251 &OrderCell)
252 || !TagOrder)
253 {
254 return -2;
255 }
256
257 /* Parse each tag */
258 for (CurrentTag = 1; CurrentTag <= TagOrder[0]; CurrentTag++)
259 {
260 /* Find a match */
261 if (TagOrder[CurrentTag] == *DriverTag)
262 {
263 /* Found it -- return the tag */
264 if (BufferAllocated) Hive->Free(TagOrder, Length);
265 return CurrentTag;
266 }
267 }
268
269 /* No matches, so assume next to last ordering */
270 if (BufferAllocated) Hive->Free(TagOrder, Length);
271 return -2;
272}
unsigned char BOOLEAN
Definition: actypes.h:127
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 1222 of file cmboot.c.

1225{
1227 PBOOT_DRIVER_NODE DriverNode;
1228
1229 /* Loop through the list and remove each driver node */
1230 while (!IsListEmpty(DriverListHead))
1231 {
1232 /* Get the driver node */
1233 Entry = RemoveHeadList(DriverListHead);
1234 DriverNode = CONTAINING_RECORD(Entry,
1236 ListEntry.Link);
1237
1238 /* Free any allocated string buffers, then the node */
1239 if (DriverNode->ListEntry.RegistryPath.Buffer)
1240 {
1241 Hive->Free(DriverNode->ListEntry.RegistryPath.Buffer,
1243 }
1244 if (DriverNode->ListEntry.FilePath.Buffer)
1245 {
1246 Hive->Free(DriverNode->ListEntry.FilePath.Buffer,
1247 DriverNode->ListEntry.FilePath.MaximumLength);
1248 }
1249 if (DriverNode->Name.Buffer)
1250 {
1251 Hive->Free(DriverNode->Name.Buffer,
1252 DriverNode->Name.MaximumLength);
1253 }
1254 Hive->Free(DriverNode, sizeof(BOOT_DRIVER_NODE));
1255 }
1256}
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
Entry
Definition: section.c:5216
UNICODE_STRING RegistryPath
Definition: arc.h:337
UNICODE_STRING FilePath
Definition: arc.h:336

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 616 of file cmboot.c.

620{
624 HCELL_INDEX ValueCell;
626 PULONG Data;
627
628 /* Sanity check: We shouldn't need to release any acquired cells */
629 ASSERT(Hive->ReleaseCellRoutine == NULL);
630
631 /* Open the start cell */
632 Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
633 if (!Node) return FALSE;
634 ValueCell = CmpFindValueByName(Hive, Node, &Name);
635 if (ValueCell == HCELL_NIL) return FALSE;
636
637 /* Read the start value */
638 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
639 if (!Value) return FALSE;
640 if (Value->Type != REG_DWORD) return FALSE;
642 if (!Data) return FALSE;
643 if (Length < sizeof(ULONG)) return FALSE;
644
645 /* Return if the type matches */
646 return (*Data == LoadType);
647}
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35

Referenced by CmpFindDrivers().

◆ CmpIsSafe()

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

Definition at line 1079 of file cmboot.c.

1083{
1084 PCM_KEY_NODE SafeBootNode;
1085 PCM_KEY_NODE DriverNode;
1086 PCM_KEY_VALUE KeyValue;
1087 HCELL_INDEX CellIndex;
1088 ULONG Length;
1090 PWCHAR Buffer;
1091
1092 /* Sanity check: We shouldn't need to release any acquired cells */
1093 ASSERT(Hive->ReleaseCellRoutine == NULL);
1094
1095 /* Driver key node (mandatory) */
1096 ASSERT(DriverCell != HCELL_NIL);
1097 DriverNode = (PCM_KEY_NODE)HvGetCell(Hive, DriverCell);
1098 if (!DriverNode) return FALSE;
1099
1100 /* Safe boot key node (optional but return TRUE if not present) */
1101 if (SafeBootCell == HCELL_NIL) return TRUE;
1102 SafeBootNode = (PCM_KEY_NODE)HvGetCell(Hive, SafeBootCell);
1103 if (!SafeBootNode) return FALSE;
1104
1105 /* Search by the name from the group */
1106 RtlInitUnicodeString(&Name, L"Group");
1107 CellIndex = CmpFindValueByName(Hive, DriverNode, &Name);
1108 if (CellIndex != HCELL_NIL)
1109 {
1110 KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
1111 if (!KeyValue) return FALSE;
1112
1113 if (KeyValue->Type == REG_SZ) // REG_EXPAND_SZ not really allowed there.
1114 {
1115 /* Compose the search 'key' */
1116 Buffer = (PWCHAR)CmpValueToData(Hive, KeyValue, &Length);
1117 if (!Buffer)
1118 return FALSE;
1120 Length -= sizeof(UNICODE_NULL);
1121
1122 Name.Buffer = Buffer;
1123 Name.Length = (USHORT)Length;
1124 Name.MaximumLength = Name.Length;
1125
1126 /* Search for corresponding key in the Safe Boot key */
1127 CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
1128 if (CellIndex != HCELL_NIL) return TRUE;
1129 }
1130 }
1131
1132 /* Group has not been found - find driver name */
1133 Length = (DriverNode->Flags & KEY_COMP_NAME) ?
1134 CmpCompressedNameSize(DriverNode->Name, DriverNode->NameLength) :
1135 DriverNode->NameLength;
1136 if (Length < sizeof(WCHAR))
1137 return FALSE;
1138
1139 /* Now allocate the buffer for it and copy the name */
1140 RtlInitEmptyUnicodeString(&Name,
1141 Hive->Allocate(Length, FALSE, TAG_CM),
1142 (USHORT)Length);
1143 if (!Name.Buffer)
1144 return FALSE;
1145
1146 Name.Length = (USHORT)Length;
1147 if (DriverNode->Flags & KEY_COMP_NAME)
1148 {
1149 /* Compressed name */
1151 Name.Length,
1152 DriverNode->Name,
1153 DriverNode->NameLength);
1154 }
1155 else
1156 {
1157 /* Normal name */
1158 RtlCopyMemory(Name.Buffer, DriverNode->Name, DriverNode->NameLength);
1159 }
1160
1161 CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
1162 Hive->Free(Name.Buffer, Name.MaximumLength);
1163 if (CellIndex != HCELL_NIL) return TRUE;
1164
1165 /* Not group or driver name - search by image name */
1166 RtlInitUnicodeString(&Name, L"ImagePath");
1167 CellIndex = CmpFindValueByName(Hive, DriverNode, &Name);
1168 if (CellIndex != HCELL_NIL)
1169 {
1170 KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex);
1171 if (!KeyValue) return FALSE;
1172
1173 if ((KeyValue->Type == REG_SZ) || (KeyValue->Type == REG_EXPAND_SZ))
1174 {
1175 /* Compose the search 'key' */
1176 Buffer = (PWCHAR)CmpValueToData(Hive, KeyValue, &Length);
1177 if (!Buffer) return FALSE;
1178 if (Length < sizeof(WCHAR)) return FALSE;
1179
1180 /* Get the base image file name */
1181 // FIXME: wcsrchr() may fail if Buffer is *not* NULL-terminated!
1183 if (!Name.Buffer) return FALSE;
1184 ++Name.Buffer;
1185
1186 /* Length of the base name must be >=1 WCHAR */
1187 if (((ULONG_PTR)Name.Buffer - (ULONG_PTR)Buffer) >= Length)
1188 return FALSE;
1189 Length -= ((ULONG_PTR)Name.Buffer - (ULONG_PTR)Buffer);
1190 if (IS_NULL_TERMINATED(Name.Buffer, Length))
1191 Length -= sizeof(UNICODE_NULL);
1192 if (Length < sizeof(WCHAR)) return FALSE;
1193
1194 Name.Length = (USHORT)Length;
1195 Name.MaximumLength = Name.Length;
1196
1197 /* Search for corresponding key in the Safe Boot key */
1198 CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name);
1199 if (CellIndex != HCELL_NIL) return TRUE;
1200 }
1201 }
1202
1203 /* Nothing found - nothing else to search */
1204 return FALSE;
1205}
#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 954 of file cmboot.c.

957{
958 PBOOT_DRIVER_NODE CurrentNode, PreviousNode;
959 PLIST_ENTRY ListEntry;
960
961 /* Base case, nothing to do */
962 if (StartNode == EndNode) return TRUE;
963
964 /* Loop the nodes */
965 CurrentNode = StartNode;
966 do
967 {
968 /* Save this as the previous node */
969 PreviousNode = CurrentNode;
970
971 /* And move to the next one */
972 ListEntry = CurrentNode->ListEntry.Link.Flink;
973 CurrentNode = CONTAINING_RECORD(ListEntry,
975 ListEntry.Link);
976
977 /* Check if the previous driver had a bigger tag */
978 if (PreviousNode->Tag > CurrentNode->Tag)
979 {
980 /* Check if we need to update the tail */
981 if (CurrentNode == EndNode)
982 {
983 /* Update the tail */
984 ListEntry = CurrentNode->ListEntry.Link.Blink;
985 EndNode = CONTAINING_RECORD(ListEntry,
987 ListEntry.Link);
988 }
989
990 /* Remove this driver since we need to move it */
991 RemoveEntryList(&CurrentNode->ListEntry.Link);
992
993 /* Keep looping until we find a driver with a lower tag than ours */
994 while ((PreviousNode->Tag > CurrentNode->Tag) && (PreviousNode != StartNode))
995 {
996 /* We'll be re-inserted at this spot */
997 ListEntry = PreviousNode->ListEntry.Link.Blink;
998 PreviousNode = CONTAINING_RECORD(ListEntry,
1000 ListEntry.Link);
1001 }
1002
1003 /* Do the insert in the new location */
1004 InsertTailList(&PreviousNode->ListEntry.Link, &CurrentNode->ListEntry.Link);
1005
1006 /* Update the head, if needed */
1007 if (PreviousNode == StartNode) StartNode = CurrentNode;
1008 }
1009 } while (CurrentNode != EndNode);
1010
1011 /* All done */
1012 return TRUE;
1013}
#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 1028 of file cmboot.c.

1030{
1031 PLIST_ENTRY NextEntry;
1032 PBOOT_DRIVER_NODE StartNode, EndNode, CurrentNode;
1033
1034 /* Loop the list */
1035 NextEntry = DriverListHead->Flink;
1036 while (NextEntry != DriverListHead)
1037 {
1038 /* Find the first entry */
1039 StartNode = CONTAINING_RECORD(NextEntry,
1041 ListEntry.Link);
1042 do
1043 {
1044 /* Find the last entry */
1045 EndNode = CONTAINING_RECORD(NextEntry,
1047 ListEntry.Link);
1048
1049 /* Get the next entry */
1050 NextEntry = NextEntry->Flink;
1051 CurrentNode = CONTAINING_RECORD(NextEntry,
1053 ListEntry.Link);
1054
1055 /* If the next entry is back to the top, break out */
1056 if (NextEntry == DriverListHead) break;
1057
1058 /* Otherwise, check if this entry is equal */
1059 if (!RtlEqualUnicodeString(&StartNode->Group,
1060 &CurrentNode->Group,
1061 TRUE))
1062 {
1063 /* It is, so we've detected a cycle, break out */
1064 break;
1065 }
1066 } while (NextEntry != DriverListHead);
1067
1068 /* Now we have the correct start and end pointers, so do the sort */
1069 CmpOrderGroup(StartNode, EndNode);
1070 }
1071
1072 /* We're done */
1073 return TRUE;
1074}
static BOOLEAN CmpOrderGroup(_In_ PBOOT_DRIVER_NODE StartNode, _In_ PBOOT_DRIVER_NODE EndNode)
Definition: cmboot.c:954

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 900 of file cmboot.c.

904{
906 PCM_KEY_VALUE ListValue;
907 HCELL_INDEX ControlCell, GroupOrder, ListCell;
908 UNICODE_STRING Name, OrderList;
910
911 /* Sanity check: We shouldn't need to release any acquired cells */
912 ASSERT(Hive->ReleaseCellRoutine == NULL);
913
914 /* Open the control key */
915 Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlSet);
916 if (!Node) return FALSE;
917 RtlInitUnicodeString(&Name, L"Control");
918 ControlCell = CmpFindSubKeyByName(Hive, Node, &Name);
919 if (ControlCell == HCELL_NIL) return FALSE;
920
921 /* Open the service group order */
922 Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlCell);
923 if (!Node) return FALSE;
924 RtlInitUnicodeString(&Name, L"ServiceGroupOrder");
925 GroupOrder = CmpFindSubKeyByName(Hive, Node, &Name);
926 if (GroupOrder == HCELL_NIL) return FALSE;
927
928 /* Open the list key */
929 Node = (PCM_KEY_NODE)HvGetCell(Hive, GroupOrder);
930 if (!Node) return FALSE;
931 RtlInitUnicodeString(&Name, L"list");
932 ListCell = CmpFindValueByName(Hive, Node, &Name);
933 if (ListCell == HCELL_NIL) return FALSE;
934
935 /* Read the actual list */
936 ListValue = (PCM_KEY_VALUE)HvGetCell(Hive, ListCell);
937 if (!ListValue) return FALSE;
938 if (ListValue->Type != REG_MULTI_SZ) return FALSE;
939
940 /* Copy it into a buffer */
941 OrderList.Buffer = (PWCHAR)CmpValueToData(Hive, ListValue, &Length);
942 if (!OrderList.Buffer) return FALSE;
943 if (!IS_NULL_TERMINATED(OrderList.Buffer, Length)) return FALSE;
944 OrderList.Length = (USHORT)Length - sizeof(UNICODE_NULL);
945 OrderList.MaximumLength = OrderList.Length;
946
947 /* And start the sort algorithm */
948 return CmpDoSort(DriverListHead, &OrderList);
949}
static BOOLEAN CmpDoSort(_Inout_ PLIST_ENTRY DriverListHead, _In_ PCUNICODE_STRING OrderList)
Performs the driver list sorting, according to the ordering list.
Definition: cmboot.c:826
#define REG_MULTI_SZ
Definition: nt_native.h:1504

Referenced by CmGetSystemDriverList(), and WinLdrScanRegistry().