2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/config/cmboot.c
5 * PURPOSE: Configuration Manager - Boot Initialization
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 * Alex Ionescu (alex.ionescu@reactos.org)
10 /* INCLUDES *******************************************************************/
16 /* GLOBALS ********************************************************************/
18 extern ULONG InitSafeBootMode
;
20 /* FUNCTIONS ******************************************************************/
25 CmpFindControlSet(IN PHHIVE SystemHive
,
26 IN HCELL_INDEX RootCell
,
27 IN PUNICODE_STRING SelectKeyName
,
28 OUT PBOOLEAN AutoSelect
)
30 UNICODE_STRING KeyName
;
32 HCELL_INDEX SelectCell
, AutoSelectCell
, SelectValueCell
, ControlSetCell
;
33 HCELL_INDEX CurrentValueCell
;
34 PCM_KEY_VALUE KeyValue
;
37 ANSI_STRING ControlSetAnsiName
;
39 WCHAR WideBuffer
[128];
44 ASSERT(SystemHive
->ReleaseCellRoutine
== NULL
);
46 /* Get the Select subkey */
47 RtlInitUnicodeString(&KeyName
, L
"select");
48 Node
= (PCM_KEY_NODE
)HvGetCell(SystemHive
, RootCell
);
49 if (!Node
) return HCELL_NIL
;
50 SelectCell
= CmpFindSubKeyByName(SystemHive
, Node
, &KeyName
);
51 if (SelectCell
== HCELL_NIL
) return SelectCell
;
53 /* Get AutoSelect value */
54 RtlInitUnicodeString(&KeyName
, L
"AutoSelect");
55 Node
= (PCM_KEY_NODE
)HvGetCell(SystemHive
, SelectCell
);
56 if (!Node
) return HCELL_NIL
;
57 AutoSelectCell
= CmpFindValueByName(SystemHive
, Node
, &KeyName
);
58 if (AutoSelectCell
== HCELL_NIL
)
60 /* Assume TRUE if the value is missing. */
66 KeyValue
= (PCM_KEY_VALUE
)HvGetCell(SystemHive
, AutoSelectCell
);
67 if (KeyValue
== NULL
) return HCELL_NIL
;
69 /* Convert it to a boolean */
70 *AutoSelect
= *(PBOOLEAN
)CmpValueToData(SystemHive
, KeyValue
, &Length
);
73 /* Now find the control set being looked up */
74 Node
= (PCM_KEY_NODE
)HvGetCell(SystemHive
, SelectCell
);
75 if (!Node
) return HCELL_NIL
;
76 SelectValueCell
= CmpFindValueByName(SystemHive
, Node
, SelectKeyName
);
77 if (SelectValueCell
== HCELL_NIL
) return SelectValueCell
;
79 /* Read the value (corresponding to the CCS ID) */
80 KeyValue
= (PCM_KEY_VALUE
)HvGetCell(SystemHive
, SelectValueCell
);
81 if (!KeyValue
) return HCELL_NIL
;
82 if (KeyValue
->Type
!= REG_DWORD
) return HCELL_NIL
;
83 ControlSetId
= (PULONG
)CmpValueToData(SystemHive
, KeyValue
, &Length
);
85 /* Now build an Ansi String for the CCS's Name */
86 sprintf(Buffer
, "ControlSet%03lu", *ControlSetId
);
87 ControlSetAnsiName
.Length
= (USHORT
)strlen(Buffer
);
88 ControlSetAnsiName
.MaximumLength
= (USHORT
)strlen(Buffer
);
89 ControlSetAnsiName
.Buffer
= Buffer
;
91 /* And convert it to Unicode... */
92 KeyName
.MaximumLength
= 256;
93 KeyName
.Buffer
= WideBuffer
;
94 Status
= RtlAnsiStringToUnicodeString(&KeyName
,
97 if (!NT_SUCCESS(Status
)) return HCELL_NIL
;
100 Node
= (PCM_KEY_NODE
)HvGetCell(SystemHive
, RootCell
);
101 if (!Node
) return HCELL_NIL
;
102 ControlSetCell
= CmpFindSubKeyByName(SystemHive
, Node
, &KeyName
);
103 if (ControlSetCell
== HCELL_NIL
) return ControlSetCell
;
105 /* Get the value of the "Current" CCS */
106 RtlInitUnicodeString(&KeyName
, L
"Current");
107 Node
= (PCM_KEY_NODE
)HvGetCell(SystemHive
, SelectCell
);
108 if (!Node
) return HCELL_NIL
;
109 CurrentValueCell
= CmpFindValueByName(SystemHive
, Node
, &KeyName
);
111 /* Make sure it exists */
112 if (CurrentValueCell
!= HCELL_NIL
)
114 /* Get the current value and make sure its a ULONG */
115 KeyValue
= (PCM_KEY_VALUE
)HvGetCell(SystemHive
, CurrentValueCell
);
116 if (!KeyValue
) return HCELL_NIL
;
117 if (KeyValue
->Type
== REG_DWORD
)
119 /* Get the data and update it */
120 CurrentData
= (PULONG
)CmpValueToData(SystemHive
,
123 if (!CurrentData
) return HCELL_NIL
;
124 *CurrentData
= *ControlSetId
;
128 /* Return the CCS Cell */
129 return ControlSetCell
;
135 CmpFindTagIndex(IN PHHIVE Hive
,
136 IN HCELL_INDEX TagCell
,
137 IN HCELL_INDEX GroupOrderCell
,
138 IN PUNICODE_STRING GroupName
)
140 PCM_KEY_VALUE TagValue
, Value
;
141 HCELL_INDEX OrderCell
;
142 PULONG TagOrder
, DriverTag
;
143 ULONG CurrentTag
, Length
;
145 BOOLEAN BufferAllocated
;
146 ASSERT(Hive
->ReleaseCellRoutine
== NULL
);
149 Value
= HvGetCell(Hive
, TagCell
);
151 DriverTag
= (PULONG
)CmpValueToData(Hive
, Value
, &Length
);
154 /* Get the order array */
155 Node
= HvGetCell(Hive
, GroupOrderCell
);
157 OrderCell
= CmpFindValueByName(Hive
, Node
, GroupName
);
158 if (OrderCell
== HCELL_NIL
) return -2;
161 TagValue
= HvGetCell(Hive
, OrderCell
);
162 CmpGetValueData(Hive
, TagValue
, &Length
, (PVOID
*)&TagOrder
, &BufferAllocated
, &OrderCell
);
166 for (CurrentTag
= 1; CurrentTag
<= TagOrder
[0]; CurrentTag
++)
169 if (TagOrder
[CurrentTag
] == *DriverTag
)
171 /* Found it -- return the tag */
172 if (BufferAllocated
) ExFreePool(TagOrder
);
177 /* No matches, so assume next to last ordering */
178 if (BufferAllocated
) ExFreePool(TagOrder
);
185 CmpAddDriverToList(IN PHHIVE Hive
,
186 IN HCELL_INDEX DriverCell
,
187 IN HCELL_INDEX GroupOrderCell
,
188 IN PUNICODE_STRING RegistryPath
,
189 IN PLIST_ENTRY BootDriverListHead
)
191 PBOOT_DRIVER_NODE DriverNode
;
192 PBOOT_DRIVER_LIST_ENTRY DriverEntry
;
196 HCELL_INDEX ValueCell
, TagCell
; PCM_KEY_VALUE Value
;
197 PUNICODE_STRING FileName
, RegistryString
;
198 UNICODE_STRING UnicodeString
;
201 ASSERT(Hive
->ReleaseCellRoutine
== NULL
);
203 /* Allocate a driver node and initialize it */
204 DriverNode
= CmpAllocate(sizeof(BOOT_DRIVER_NODE
), FALSE
, TAG_CM
);
205 if (!DriverNode
) return FALSE
;
206 DriverEntry
= &DriverNode
->ListEntry
;
207 DriverEntry
->RegistryPath
.Buffer
= NULL
;
208 DriverEntry
->FilePath
.Buffer
= NULL
;
210 /* Get the driver cell */
211 Node
= HvGetCell(Hive
, DriverCell
);
214 /* Get the name from the cell */
215 DriverNode
->Name
.Length
= Node
->Flags
& KEY_COMP_NAME
?
216 CmpCompressedNameSize(Node
->Name
, Node
->NameLength
) :
218 DriverNode
->Name
.MaximumLength
= DriverNode
->Name
.Length
;
219 NameLength
= DriverNode
->Name
.Length
;
221 /* Now allocate the buffer for it and copy the name */
222 DriverNode
->Name
.Buffer
= CmpAllocate(NameLength
, FALSE
, TAG_CM
);
223 if (!DriverNode
->Name
.Buffer
) return FALSE
;
224 if (Node
->Flags
& KEY_COMP_NAME
)
226 /* Compressed name */
227 CmpCopyCompressedName(DriverNode
->Name
.Buffer
,
228 DriverNode
->Name
.Length
,
235 RtlCopyMemory(DriverNode
->Name
.Buffer
, Node
->Name
, Node
->NameLength
);
238 /* Now find the image path */
239 RtlInitUnicodeString(&UnicodeString
, L
"ImagePath");
240 ValueCell
= CmpFindValueByName(Hive
, Node
, &UnicodeString
);
241 if (ValueCell
== HCELL_NIL
)
243 /* Couldn't find it, so assume the drivers path */
244 Length
= sizeof(L
"System32\\Drivers\\") + NameLength
+ sizeof(L
".sys");
246 /* Allocate the path name */
247 FileName
= &DriverEntry
->FilePath
;
248 FileName
->Length
= 0;
249 FileName
->MaximumLength
= (USHORT
)Length
;
250 FileName
->Buffer
= CmpAllocate(Length
, FALSE
,TAG_CM
);
251 if (!FileName
->Buffer
) return FALSE
;
253 /* Write the path name */
254 RtlAppendUnicodeToString(FileName
, L
"System32\\Drivers\\");
255 RtlAppendUnicodeStringToString(FileName
, &DriverNode
->Name
);
256 RtlAppendUnicodeToString(FileName
, L
".sys");
260 /* Path name exists, so grab it */
261 Value
= HvGetCell(Hive
, ValueCell
);
264 /* Allocate and setup the path name */
265 FileName
= &DriverEntry
->FilePath
;
266 Buffer
= (PWCHAR
)CmpValueToData(Hive
, Value
, &Length
);
267 FileName
->MaximumLength
= FileName
->Length
= (USHORT
)Length
;
268 FileName
->Buffer
= CmpAllocate(Length
, FALSE
, TAG_CM
);
270 /* Transfer the data */
271 if (!(FileName
->Buffer
) || !(Buffer
)) return FALSE
;
272 RtlCopyMemory(FileName
->Buffer
, Buffer
, Length
);
275 /* Now build the registry path */
276 RegistryString
= &DriverEntry
->RegistryPath
;
277 RegistryString
->Length
= 0;
278 RegistryString
->MaximumLength
= RegistryPath
->Length
+ NameLength
;
279 RegistryString
->Buffer
= CmpAllocate(RegistryString
->MaximumLength
, FALSE
, TAG_CM
);
280 if (!RegistryString
->Buffer
) return FALSE
;
282 /* Add the driver name to it */
283 RtlAppendUnicodeStringToString(RegistryString
, RegistryPath
);
284 RtlAppendUnicodeStringToString(RegistryString
, &DriverNode
->Name
);
286 /* The entry is done, add it */
287 InsertHeadList(BootDriverListHead
, &DriverEntry
->Link
);
289 /* Now find error control settings */
290 RtlInitUnicodeString(&UnicodeString
, L
"ErrorControl");
291 ValueCell
= CmpFindValueByName(Hive
, Node
, &UnicodeString
);
292 if (ValueCell
== HCELL_NIL
)
294 /* Couldn't find it, so assume default */
295 DriverNode
->ErrorControl
= NormalError
;
299 /* Otherwise, read whatever the data says */
300 Value
= HvGetCell(Hive
, ValueCell
);
302 ErrorControl
= (PULONG
)CmpValueToData(Hive
, Value
, &Length
);
303 ASSERT(ErrorControl
);
304 DriverNode
->ErrorControl
= *ErrorControl
;
307 /* Next, get the group cell */
308 RtlInitUnicodeString(&UnicodeString
, L
"group");
309 ValueCell
= CmpFindValueByName(Hive
, Node
, &UnicodeString
);
310 if (ValueCell
== HCELL_NIL
)
312 /* Couldn't find, so set an empty string */
313 RtlInitEmptyUnicodeString(&DriverNode
->Group
, NULL
, 0);
317 /* Found it, read the group value */
318 Value
= HvGetCell(Hive
, ValueCell
);
321 /* Copy it into the node */
322 DriverNode
->Group
.Buffer
= (PWCHAR
)CmpValueToData(Hive
, Value
, &Length
);
323 if (!DriverNode
->Group
.Buffer
) return FALSE
;
324 DriverNode
->Group
.Length
= (USHORT
)Length
- sizeof(UNICODE_NULL
);
325 DriverNode
->Group
.MaximumLength
= DriverNode
->Group
.Length
;
328 /* Finally, find the tag */
329 RtlInitUnicodeString(&UnicodeString
, L
"Tag");
330 TagCell
= CmpFindValueByName(Hive
, Node
, &UnicodeString
);
331 if (TagCell
== HCELL_NIL
)
333 /* No tag, so load last */
334 DriverNode
->Tag
= -1;
338 /* Otherwise, decode it based on tag order */
339 DriverNode
->Tag
= CmpFindTagIndex(Hive
,
352 CmpIsLoadType(IN PHHIVE Hive
,
354 IN SERVICE_LOAD_TYPE LoadType
)
357 HCELL_INDEX ValueCell
;
358 UNICODE_STRING ValueString
= RTL_CONSTANT_STRING(L
"Start");
362 ASSERT(Hive
->ReleaseCellRoutine
== NULL
);
364 /* Open the start cell */
365 Node
= HvGetCell(Hive
, Cell
);
367 ValueCell
= CmpFindValueByName(Hive
, Node
, &ValueString
);
368 if (ValueCell
== HCELL_NIL
) return FALSE
;
370 /* Read the start value */
371 Value
= HvGetCell(Hive
, ValueCell
);
373 Data
= (PLONG
)CmpValueToData(Hive
, Value
, &Length
);
376 /* Return if the type matches */
377 return (*Data
== LoadType
);
383 CmpFindDrivers(IN PHHIVE Hive
,
384 IN HCELL_INDEX ControlSet
,
385 IN SERVICE_LOAD_TYPE LoadType
,
386 IN PWCHAR BootFileSystem OPTIONAL
,
387 IN PLIST_ENTRY DriverListHead
)
389 HCELL_INDEX ServicesCell
, ControlCell
, GroupOrderCell
, DriverCell
;
390 HCELL_INDEX SafeBootCell
= HCELL_NIL
;
394 UNICODE_STRING UnicodeString
, KeyPath
;
395 PBOOT_DRIVER_NODE FsNode
;
396 PCM_KEY_NODE ControlNode
, ServicesNode
, Node
;
397 ASSERT(Hive
->ReleaseCellRoutine
== NULL
);
399 /* Open the control set key */
400 ControlNode
= HvGetCell(Hive
, ControlSet
);
403 /* Get services cell */
404 RtlInitUnicodeString(&Name
, L
"Services");
405 ServicesCell
= CmpFindSubKeyByName(Hive
, ControlNode
, &Name
);
406 if (ServicesCell
== HCELL_NIL
) return FALSE
;
408 /* Open services key */
409 ServicesNode
= HvGetCell(Hive
, ServicesCell
);
410 ASSERT(ServicesNode
);
412 /* Get control cell */
413 RtlInitUnicodeString(&Name
, L
"Control");
414 ControlCell
= CmpFindSubKeyByName(Hive
, ControlNode
, &Name
);
415 if (ControlCell
== HCELL_NIL
) return FALSE
;
417 /* Get the group order cell and read it */
418 RtlInitUnicodeString(&Name
, L
"GroupOrderList");
419 Node
= HvGetCell(Hive
, ControlCell
);
421 GroupOrderCell
= CmpFindSubKeyByName(Hive
, Node
, &Name
);
422 if (GroupOrderCell
== HCELL_NIL
) return FALSE
;
424 /* Get Safe Boot cell */
427 /* Open the Safe Boot key */
428 RtlInitUnicodeString(&Name
, L
"SafeBoot");
429 Node
= HvGetCell(Hive
, ControlCell
);
431 SafeBootCell
= CmpFindSubKeyByName(Hive
, Node
, &Name
);
432 if (SafeBootCell
== HCELL_NIL
) return FALSE
;
434 /* Open the correct start key (depending on the mode) */
435 Node
= HvGetCell(Hive
, SafeBootCell
);
437 switch(InitSafeBootMode
)
439 /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
441 case 3: RtlInitUnicodeString(&Name
, L
"Minimal"); break;
442 case 2: RtlInitUnicodeString(&Name
, L
"Network"); break;
443 default: return FALSE
;
445 SafeBootCell
= CmpFindSubKeyByName(Hive
, Node
, &Name
);
446 if(SafeBootCell
== HCELL_NIL
) return FALSE
;
449 /* Build the root registry path */
450 RtlInitEmptyUnicodeString(&KeyPath
, Buffer
, sizeof(Buffer
));
451 RtlAppendUnicodeToString(&KeyPath
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
453 /* Find the first subkey (ie: the first driver or service) */
455 DriverCell
= CmpFindSubKeyByNumber(Hive
, ServicesNode
, i
);
456 while (DriverCell
!= HCELL_NIL
)
458 /* Make sure it's a driver of this start type AND is "safe" to load */
459 if (CmpIsLoadType(Hive
, DriverCell
, LoadType
) &&
460 CmpIsSafe(Hive
, SafeBootCell
, DriverCell
))
462 /* Add it to the list */
463 CmpAddDriverToList(Hive
,
471 /* Try the next subkey */
472 DriverCell
= CmpFindSubKeyByNumber(Hive
, ServicesNode
, ++i
);
475 /* Check if we have a boot file system */
479 RtlInitUnicodeString(&UnicodeString
, BootFileSystem
);
480 DriverCell
= CmpFindSubKeyByName(Hive
, ServicesNode
, &UnicodeString
);
481 if (DriverCell
!= HCELL_NIL
)
483 /* Always add it to the list */
484 CmpAddDriverToList(Hive
,
490 /* Mark it as critical so it always loads */
491 FsNode
= CONTAINING_RECORD(DriverListHead
->Flink
,
494 FsNode
->ErrorControl
= SERVICE_ERROR_CRITICAL
;
505 CmpDoSort(IN PLIST_ENTRY DriverListHead
,
506 IN PUNICODE_STRING OrderList
)
508 PWCHAR Current
, End
= NULL
;
509 PLIST_ENTRY NextEntry
;
510 UNICODE_STRING GroupName
;
511 PBOOT_DRIVER_NODE CurrentNode
;
513 /* We're going from end to start, so get to the last group and keep going */
514 Current
= &OrderList
->Buffer
[OrderList
->Length
/ sizeof(WCHAR
)];
515 while (Current
> OrderList
->Buffer
)
517 /* Scan the current string */
520 if (*Current
== UNICODE_NULL
) End
= Current
;
521 } while ((*(--Current
- 1) != UNICODE_NULL
) && (Current
!= OrderList
->Buffer
));
523 /* This is our cleaned up string for this specific group */
525 GroupName
.Length
= (USHORT
)(End
- Current
) * sizeof(WCHAR
);
526 GroupName
.MaximumLength
= GroupName
.Length
;
527 GroupName
.Buffer
= Current
;
529 /* Now loop the driver list */
530 NextEntry
= DriverListHead
->Flink
;
531 while (NextEntry
!= DriverListHead
)
534 CurrentNode
= CONTAINING_RECORD(NextEntry
,
538 /* Get the next entry now since we'll do a relink */
539 NextEntry
= CurrentNode
->ListEntry
.Link
.Flink
;
541 /* Is there a group name and does it match the current group? */
542 if ((CurrentNode
->Group
.Buffer
) &&
543 (RtlEqualUnicodeString(&GroupName
, &CurrentNode
->Group
, TRUE
)))
545 /* Remove from this location and re-link in the new one */
546 RemoveEntryList(&CurrentNode
->ListEntry
.Link
);
547 InsertHeadList(DriverListHead
, &CurrentNode
->ListEntry
.Link
);
562 CmpSortDriverList(IN PHHIVE Hive
,
563 IN HCELL_INDEX ControlSet
,
564 IN PLIST_ENTRY DriverListHead
)
566 HCELL_INDEX Controls
, GroupOrder
, ListCell
;
567 UNICODE_STRING Name
, DependList
;
568 PCM_KEY_VALUE ListNode
;
571 ASSERT(Hive
->ReleaseCellRoutine
== NULL
);
573 /* Open the control key */
574 Node
= HvGetCell(Hive
, ControlSet
);
576 RtlInitUnicodeString(&Name
, L
"Control");
577 Controls
= CmpFindSubKeyByName(Hive
, Node
, &Name
);
578 if (Controls
== HCELL_NIL
) return FALSE
;
580 /* Open the service group order */
581 Node
= HvGetCell(Hive
, Controls
);
583 RtlInitUnicodeString(&Name
, L
"ServiceGroupOrder");
584 GroupOrder
= CmpFindSubKeyByName(Hive
, Node
, &Name
);
585 if (GroupOrder
== HCELL_NIL
) return FALSE
;
587 /* Open the list key */
588 Node
= HvGetCell(Hive
, GroupOrder
);
590 RtlInitUnicodeString(&Name
, L
"list");
591 ListCell
= CmpFindValueByName(Hive
, Node
, &Name
);
592 if (ListCell
== HCELL_NIL
) return FALSE
;
594 /* Now read the actual list */
595 ListNode
= HvGetCell(Hive
, ListCell
);
597 if (ListNode
->Type
!= REG_MULTI_SZ
) return FALSE
;
599 /* Copy it into a buffer */
600 DependList
.Buffer
= (PWCHAR
)CmpValueToData(Hive
, ListNode
, &Length
);
601 if (!DependList
.Buffer
) return FALSE
;
602 DependList
.Length
= DependList
.MaximumLength
= (USHORT
)Length
- sizeof(UNICODE_NULL
);
604 /* And start the recurive sort algorithm */
605 return CmpDoSort(DriverListHead
, &DependList
);
611 CmpOrderGroup(IN PBOOT_DRIVER_NODE StartNode
,
612 IN PBOOT_DRIVER_NODE EndNode
)
614 PBOOT_DRIVER_NODE CurrentNode
, PreviousNode
;
615 PLIST_ENTRY ListEntry
;
617 /* Base case, nothing to do */
618 if (StartNode
== EndNode
) return TRUE
;
621 CurrentNode
= StartNode
;
624 /* Save this as the previous node */
625 PreviousNode
= CurrentNode
;
627 /* And move to the next one */
628 ListEntry
= CurrentNode
->ListEntry
.Link
.Flink
;
629 CurrentNode
= CONTAINING_RECORD(ListEntry
,
633 /* Check if the previous driver had a bigger tag */
634 if (PreviousNode
->Tag
> CurrentNode
->Tag
)
636 /* Check if we need to update the tail */
637 if (CurrentNode
== EndNode
)
639 /* Update the tail */
640 ListEntry
= CurrentNode
->ListEntry
.Link
.Blink
;
641 EndNode
= CONTAINING_RECORD(ListEntry
,
646 /* Remove this driver since we need to move it */
647 RemoveEntryList(&CurrentNode
->ListEntry
.Link
);
649 /* Keep looping until we find a driver with a lower tag than ours */
650 while ((PreviousNode
->Tag
> CurrentNode
->Tag
) && (PreviousNode
!= StartNode
))
652 /* We'll be re-inserted at this spot */
653 ListEntry
= PreviousNode
->ListEntry
.Link
.Blink
;
654 PreviousNode
= CONTAINING_RECORD(ListEntry
,
659 /* Do the insert in the new location */
660 InsertTailList(&PreviousNode
->ListEntry
.Link
, &CurrentNode
->ListEntry
.Link
);
662 /* Update the head, if needed */
663 if (PreviousNode
== StartNode
) StartNode
= CurrentNode
;
665 } while (CurrentNode
!= EndNode
);
674 CmpResolveDriverDependencies(IN PLIST_ENTRY DriverListHead
)
676 PLIST_ENTRY NextEntry
;
677 PBOOT_DRIVER_NODE StartNode
, EndNode
, CurrentNode
;
680 NextEntry
= DriverListHead
->Flink
;
681 while (NextEntry
!= DriverListHead
)
683 /* Find the first entry */
684 StartNode
= CONTAINING_RECORD(NextEntry
,
689 /* Find the last entry */
690 EndNode
= CONTAINING_RECORD(NextEntry
,
694 /* Get the next entry */
695 NextEntry
= NextEntry
->Flink
;
696 CurrentNode
= CONTAINING_RECORD(NextEntry
,
700 /* If the next entry is back to the top, break out */
701 if (NextEntry
== DriverListHead
) break;
703 /* Otherwise, check if this entry is equal */
704 if (!RtlEqualUnicodeString(&StartNode
->Group
,
708 /* It is, so we've detected a cycle, break out */
711 } while (NextEntry
!= DriverListHead
);
713 /* Now we have the correct start and end pointers, so do the sort */
714 CmpOrderGroup(StartNode
, EndNode
);
724 CmpIsSafe(IN PHHIVE Hive
,
725 IN HCELL_INDEX SafeBootCell
,
726 IN HCELL_INDEX DriverCell
)
728 PCM_KEY_NODE SafeBootNode
;
729 PCM_KEY_NODE DriverNode
;
730 PCM_KEY_VALUE KeyValue
;
731 HCELL_INDEX CellIndex
;
735 ASSERT(Hive
->ReleaseCellRoutine
== NULL
);
737 /* Driver key node (mandatory) */
738 ASSERT(DriverCell
!= HCELL_NIL
);
739 DriverNode
= HvGetCell(Hive
, DriverCell
);
742 /* Safe boot key node (optional but return TRUE if not present) */
743 if(SafeBootCell
== HCELL_NIL
) return TRUE
;
744 SafeBootNode
= HvGetCell(Hive
, SafeBootCell
);
745 if(!SafeBootNode
) return FALSE
;
747 /* Search by the name from the group */
748 RtlInitUnicodeString(&Name
, L
"Group");
749 CellIndex
= CmpFindValueByName(Hive
, DriverNode
, &Name
);
750 if(CellIndex
!= HCELL_NIL
)
752 KeyValue
= HvGetCell(Hive
, CellIndex
);
754 if (KeyValue
->Type
== REG_SZ
|| KeyValue
->Type
== REG_EXPAND_SZ
)
756 /* Compose the search 'key' */
757 Name
.Buffer
= (PWCHAR
)CmpValueToData(Hive
, KeyValue
, &Length
);
758 if (!Name
.Buffer
) return FALSE
;
759 Name
.Length
= (USHORT
)Length
- sizeof(UNICODE_NULL
);
760 Name
.MaximumLength
= Name
.Length
;
761 /* Search for corresponding key in the Safe Boot key */
762 CellIndex
= CmpFindSubKeyByName(Hive
, SafeBootNode
, &Name
);
763 if(CellIndex
!= HCELL_NIL
) return TRUE
;
767 /* Group has not been found - find driver name */
768 Name
.Length
= DriverNode
->Flags
& KEY_COMP_NAME
?
769 CmpCompressedNameSize(DriverNode
->Name
,
770 DriverNode
->NameLength
) :
771 DriverNode
->NameLength
;
772 Name
.MaximumLength
= Name
.Length
;
773 /* Now allocate the buffer for it and copy the name */
774 Name
.Buffer
= CmpAllocate(Name
.Length
, FALSE
, TAG_CM
);
775 if (!Name
.Buffer
) return FALSE
;
776 if (DriverNode
->Flags
& KEY_COMP_NAME
)
778 /* Compressed name */
779 CmpCopyCompressedName(Name
.Buffer
,
782 DriverNode
->NameLength
);
787 RtlCopyMemory(Name
.Buffer
, DriverNode
->Name
, DriverNode
->NameLength
);
789 CellIndex
= CmpFindSubKeyByName(Hive
, SafeBootNode
, &Name
);
790 RtlFreeUnicodeString(&Name
);
791 if(CellIndex
!= HCELL_NIL
) return TRUE
;
793 /* Not group or driver name - search by image name */
794 RtlInitUnicodeString(&Name
, L
"ImagePath");
795 CellIndex
= CmpFindValueByName(Hive
, DriverNode
, &Name
);
796 if(CellIndex
!= HCELL_NIL
)
798 KeyValue
= HvGetCell(Hive
, CellIndex
);
800 if (KeyValue
->Type
== REG_SZ
|| KeyValue
->Type
== REG_EXPAND_SZ
)
802 /* Compose the search 'key' */
803 OriginalName
= (PWCHAR
)CmpValueToData(Hive
, KeyValue
, &Length
);
804 if (!OriginalName
) return FALSE
;
805 /* Get the base image file name */
806 Name
.Buffer
= wcsrchr(OriginalName
, L
'\\');
807 if (!Name
.Buffer
) return FALSE
;
809 /* Length of the base name must be >=1 */
810 Name
.Length
= (USHORT
)Length
- (USHORT
)((PUCHAR
)Name
.Buffer
- (PUCHAR
)OriginalName
)
811 - sizeof(UNICODE_NULL
);
812 if(Name
.Length
< 1) return FALSE
;
813 Name
.MaximumLength
= Name
.Length
;
814 /* Search for corresponding key in the Safe Boot key */
815 CellIndex
= CmpFindSubKeyByName(Hive
, SafeBootNode
, &Name
);
816 if(CellIndex
!= HCELL_NIL
) return TRUE
;
819 /* Nothing found - nothing else to search */