Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencmboot.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: ntoskrnl/config/cmboot.c 00005 * PURPOSE: Configuration Manager - Boot Initialization 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 * Alex Ionescu (alex.ionescu@reactos.org) 00008 */ 00009 00010 /* INCLUDES *******************************************************************/ 00011 00012 #include "ntoskrnl.h" 00013 #define NDEBUG 00014 #include "debug.h" 00015 00016 /* GLOBALS ********************************************************************/ 00017 00018 extern ULONG InitSafeBootMode; 00019 00020 /* FUNCTIONS ******************************************************************/ 00021 00022 HCELL_INDEX 00023 NTAPI 00024 INIT_FUNCTION 00025 CmpFindControlSet(IN PHHIVE SystemHive, 00026 IN HCELL_INDEX RootCell, 00027 IN PUNICODE_STRING SelectKeyName, 00028 OUT PBOOLEAN AutoSelect) 00029 { 00030 UNICODE_STRING KeyName; 00031 PCM_KEY_NODE Node; 00032 HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell; 00033 HCELL_INDEX CurrentValueCell; 00034 PCM_KEY_VALUE KeyValue; 00035 ULONG Length; 00036 PULONG ControlSetId; 00037 ANSI_STRING ControlSetAnsiName; 00038 CHAR Buffer[128]; 00039 WCHAR WideBuffer[128]; 00040 NTSTATUS Status; 00041 PULONG CurrentData; 00042 00043 /* Sanity check */ 00044 ASSERT(SystemHive->ReleaseCellRoutine == NULL); 00045 00046 /* Get the Select subkey */ 00047 RtlInitUnicodeString(&KeyName, L"select"); 00048 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell); 00049 if (!Node) return HCELL_NIL; 00050 SelectCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName); 00051 if (SelectCell == HCELL_NIL) return SelectCell; 00052 00053 /* Get AutoSelect value */ 00054 RtlInitUnicodeString(&KeyName, L"AutoSelect"); 00055 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell); 00056 if (!Node) return HCELL_NIL; 00057 AutoSelectCell = CmpFindValueByName(SystemHive, Node, &KeyName); 00058 if (AutoSelectCell == HCELL_NIL) 00059 { 00060 /* Assume TRUE if the value is missing. */ 00061 *AutoSelect = TRUE; 00062 } 00063 else 00064 { 00065 /* Read the value */ 00066 KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell); 00067 if (KeyValue == NULL) return HCELL_NIL; 00068 00069 /* Convert it to a boolean */ 00070 *AutoSelect = *(PBOOLEAN)CmpValueToData(SystemHive, KeyValue, &Length); 00071 } 00072 00073 /* Now find the control set being looked up */ 00074 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell); 00075 if (!Node) return HCELL_NIL; 00076 SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName); 00077 if (SelectValueCell == HCELL_NIL) return SelectValueCell; 00078 00079 /* Read the value (corresponding to the CCS ID) */ 00080 KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell); 00081 if (!KeyValue) return HCELL_NIL; 00082 if (KeyValue->Type != REG_DWORD) return HCELL_NIL; 00083 ControlSetId = (PULONG)CmpValueToData(SystemHive, KeyValue, &Length); 00084 00085 /* Now build an Ansi String for the CCS's Name */ 00086 sprintf(Buffer, "ControlSet%03lu", *ControlSetId); 00087 ControlSetAnsiName.Length = (USHORT)strlen(Buffer); 00088 ControlSetAnsiName.MaximumLength = (USHORT)strlen(Buffer); 00089 ControlSetAnsiName.Buffer = Buffer; 00090 00091 /* And convert it to Unicode... */ 00092 KeyName.MaximumLength = 256; 00093 KeyName.Buffer = WideBuffer; 00094 Status = RtlAnsiStringToUnicodeString(&KeyName, 00095 &ControlSetAnsiName, 00096 FALSE); 00097 if (!NT_SUCCESS(Status)) return HCELL_NIL; 00098 00099 /* Now open it */ 00100 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell); 00101 if (!Node) return HCELL_NIL; 00102 ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName); 00103 if (ControlSetCell == HCELL_NIL) return ControlSetCell; 00104 00105 /* Get the value of the "Current" CCS */ 00106 RtlInitUnicodeString(&KeyName, L"Current"); 00107 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell); 00108 if (!Node) return HCELL_NIL; 00109 CurrentValueCell = CmpFindValueByName(SystemHive, Node, &KeyName); 00110 00111 /* Make sure it exists */ 00112 if (CurrentValueCell != HCELL_NIL) 00113 { 00114 /* Get the current value and make sure its a ULONG */ 00115 KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell); 00116 if (!KeyValue) return HCELL_NIL; 00117 if (KeyValue->Type == REG_DWORD) 00118 { 00119 /* Get the data and update it */ 00120 CurrentData = (PULONG)CmpValueToData(SystemHive, 00121 KeyValue, 00122 &Length); 00123 if (!CurrentData) return HCELL_NIL; 00124 *CurrentData = *ControlSetId; 00125 } 00126 } 00127 00128 /* Return the CCS Cell */ 00129 return ControlSetCell; 00130 } 00131 00132 ULONG 00133 NTAPI 00134 INIT_FUNCTION 00135 CmpFindTagIndex(IN PHHIVE Hive, 00136 IN HCELL_INDEX TagCell, 00137 IN HCELL_INDEX GroupOrderCell, 00138 IN PUNICODE_STRING GroupName) 00139 { 00140 PCM_KEY_VALUE TagValue, Value; 00141 HCELL_INDEX OrderCell; 00142 PULONG TagOrder, DriverTag; 00143 ULONG CurrentTag, Length; 00144 PCM_KEY_NODE Node; 00145 BOOLEAN BufferAllocated; 00146 ASSERT(Hive->ReleaseCellRoutine == NULL); 00147 00148 /* Get the tag */ 00149 Value = HvGetCell(Hive, TagCell); 00150 ASSERT(Value); 00151 DriverTag = (PULONG)CmpValueToData(Hive, Value, &Length); 00152 ASSERT(DriverTag); 00153 00154 /* Get the order array */ 00155 Node = HvGetCell(Hive, GroupOrderCell); 00156 ASSERT(Node); 00157 OrderCell = CmpFindValueByName(Hive, Node, GroupName); 00158 if (OrderCell == HCELL_NIL) return -2; 00159 00160 /* And read it */ 00161 TagValue = HvGetCell(Hive, OrderCell); 00162 CmpGetValueData(Hive, TagValue, &Length, (PVOID*)&TagOrder, &BufferAllocated, &OrderCell); 00163 ASSERT(TagOrder); 00164 00165 /* Parse each tag */ 00166 for (CurrentTag = 1; CurrentTag <= TagOrder[0]; CurrentTag++) 00167 { 00168 /* Find a match */ 00169 if (TagOrder[CurrentTag] == *DriverTag) 00170 { 00171 /* Found it -- return the tag */ 00172 if (BufferAllocated) ExFreePool(TagOrder); 00173 return CurrentTag; 00174 } 00175 } 00176 00177 /* No matches, so assume next to last ordering */ 00178 if (BufferAllocated) ExFreePool(TagOrder); 00179 return -2; 00180 } 00181 00182 BOOLEAN 00183 NTAPI 00184 INIT_FUNCTION 00185 CmpAddDriverToList(IN PHHIVE Hive, 00186 IN HCELL_INDEX DriverCell, 00187 IN HCELL_INDEX GroupOrderCell, 00188 IN PUNICODE_STRING RegistryPath, 00189 IN PLIST_ENTRY BootDriverListHead) 00190 { 00191 PBOOT_DRIVER_NODE DriverNode; 00192 PBOOT_DRIVER_LIST_ENTRY DriverEntry; 00193 PCM_KEY_NODE Node; 00194 ULONG Length; 00195 USHORT NameLength; 00196 HCELL_INDEX ValueCell, TagCell; PCM_KEY_VALUE Value; 00197 PUNICODE_STRING FileName, RegistryString; 00198 UNICODE_STRING UnicodeString; 00199 PULONG ErrorControl; 00200 PWCHAR Buffer; 00201 ASSERT(Hive->ReleaseCellRoutine == NULL); 00202 00203 /* Allocate a driver node and initialize it */ 00204 DriverNode = CmpAllocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM); 00205 if (!DriverNode) return FALSE; 00206 DriverEntry = &DriverNode->ListEntry; 00207 DriverEntry->RegistryPath.Buffer = NULL; 00208 DriverEntry->FilePath.Buffer = NULL; 00209 00210 /* Get the driver cell */ 00211 Node = HvGetCell(Hive, DriverCell); 00212 ASSERT(Node); 00213 00214 /* Get the name from the cell */ 00215 DriverNode->Name.Length = Node->Flags & KEY_COMP_NAME ? 00216 CmpCompressedNameSize(Node->Name, Node->NameLength) : 00217 Node->NameLength; 00218 DriverNode->Name.MaximumLength = DriverNode->Name.Length; 00219 NameLength = DriverNode->Name.Length; 00220 00221 /* Now allocate the buffer for it and copy the name */ 00222 DriverNode->Name.Buffer = CmpAllocate(NameLength, FALSE, TAG_CM); 00223 if (!DriverNode->Name.Buffer) return FALSE; 00224 if (Node->Flags & KEY_COMP_NAME) 00225 { 00226 /* Compressed name */ 00227 CmpCopyCompressedName(DriverNode->Name.Buffer, 00228 DriverNode->Name.Length, 00229 Node->Name, 00230 Node->NameLength); 00231 } 00232 else 00233 { 00234 /* Normal name */ 00235 RtlCopyMemory(DriverNode->Name.Buffer, Node->Name, Node->NameLength); 00236 } 00237 00238 /* Now find the image path */ 00239 RtlInitUnicodeString(&UnicodeString, L"ImagePath"); 00240 ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString); 00241 if (ValueCell == HCELL_NIL) 00242 { 00243 /* Couldn't find it, so assume the drivers path */ 00244 Length = sizeof(L"System32\\Drivers\\") + NameLength + sizeof(L".sys"); 00245 00246 /* Allocate the path name */ 00247 FileName = &DriverEntry->FilePath; 00248 FileName->Length = 0; 00249 FileName->MaximumLength = (USHORT)Length; 00250 FileName->Buffer = CmpAllocate(Length, FALSE,TAG_CM); 00251 if (!FileName->Buffer) return FALSE; 00252 00253 /* Write the path name */ 00254 RtlAppendUnicodeToString(FileName, L"System32\\Drivers\\"); 00255 RtlAppendUnicodeStringToString(FileName, &DriverNode->Name); 00256 RtlAppendUnicodeToString(FileName, L".sys"); 00257 } 00258 else 00259 { 00260 /* Path name exists, so grab it */ 00261 Value = HvGetCell(Hive, ValueCell); 00262 ASSERT(Value); 00263 00264 /* Allocate and setup the path name */ 00265 FileName = &DriverEntry->FilePath; 00266 Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length); 00267 FileName->MaximumLength = FileName->Length = (USHORT)Length; 00268 FileName->Buffer = CmpAllocate(Length, FALSE, TAG_CM); 00269 00270 /* Transfer the data */ 00271 if (!(FileName->Buffer) || !(Buffer)) return FALSE; 00272 RtlCopyMemory(FileName->Buffer, Buffer, Length); 00273 } 00274 00275 /* Now build the registry path */ 00276 RegistryString = &DriverEntry->RegistryPath; 00277 RegistryString->Length = 0; 00278 RegistryString->MaximumLength = RegistryPath->Length + NameLength; 00279 RegistryString->Buffer = CmpAllocate(RegistryString->MaximumLength, FALSE, TAG_CM); 00280 if (!RegistryString->Buffer) return FALSE; 00281 00282 /* Add the driver name to it */ 00283 RtlAppendUnicodeStringToString(RegistryString, RegistryPath); 00284 RtlAppendUnicodeStringToString(RegistryString, &DriverNode->Name); 00285 00286 /* The entry is done, add it */ 00287 InsertHeadList(BootDriverListHead, &DriverEntry->Link); 00288 00289 /* Now find error control settings */ 00290 RtlInitUnicodeString(&UnicodeString, L"ErrorControl"); 00291 ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString); 00292 if (ValueCell == HCELL_NIL) 00293 { 00294 /* Couldn't find it, so assume default */ 00295 DriverNode->ErrorControl = NormalError; 00296 } 00297 else 00298 { 00299 /* Otherwise, read whatever the data says */ 00300 Value = HvGetCell(Hive, ValueCell); 00301 ASSERT(Value); 00302 ErrorControl = (PULONG)CmpValueToData(Hive, Value, &Length); 00303 ASSERT(ErrorControl); 00304 DriverNode->ErrorControl = *ErrorControl; 00305 } 00306 00307 /* Next, get the group cell */ 00308 RtlInitUnicodeString(&UnicodeString, L"group"); 00309 ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString); 00310 if (ValueCell == HCELL_NIL) 00311 { 00312 /* Couldn't find, so set an empty string */ 00313 RtlInitEmptyUnicodeString(&DriverNode->Group, NULL, 0); 00314 } 00315 else 00316 { 00317 /* Found it, read the group value */ 00318 Value = HvGetCell(Hive, ValueCell); 00319 ASSERT(Value); 00320 00321 /* Copy it into the node */ 00322 DriverNode->Group.Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length); 00323 if (!DriverNode->Group.Buffer) return FALSE; 00324 DriverNode->Group.Length = (USHORT)Length - sizeof(UNICODE_NULL); 00325 DriverNode->Group.MaximumLength = DriverNode->Group.Length; 00326 } 00327 00328 /* Finally, find the tag */ 00329 RtlInitUnicodeString(&UnicodeString, L"Tag"); 00330 TagCell = CmpFindValueByName(Hive, Node, &UnicodeString); 00331 if (TagCell == HCELL_NIL) 00332 { 00333 /* No tag, so load last */ 00334 DriverNode->Tag = -1; 00335 } 00336 else 00337 { 00338 /* Otherwise, decode it based on tag order */ 00339 DriverNode->Tag = CmpFindTagIndex(Hive, 00340 TagCell, 00341 GroupOrderCell, 00342 &DriverNode->Group); 00343 } 00344 00345 /* All done! */ 00346 return TRUE; 00347 } 00348 00349 BOOLEAN 00350 NTAPI 00351 INIT_FUNCTION 00352 CmpIsLoadType(IN PHHIVE Hive, 00353 IN HCELL_INDEX Cell, 00354 IN SERVICE_LOAD_TYPE LoadType) 00355 { 00356 PCM_KEY_NODE Node; 00357 HCELL_INDEX ValueCell; 00358 UNICODE_STRING ValueString = RTL_CONSTANT_STRING(L"Start"); 00359 PCM_KEY_VALUE Value; 00360 ULONG Length; 00361 PLONG Data; 00362 ASSERT(Hive->ReleaseCellRoutine == NULL); 00363 00364 /* Open the start cell */ 00365 Node = HvGetCell(Hive, Cell); 00366 ASSERT(Node); 00367 ValueCell = CmpFindValueByName(Hive, Node, &ValueString); 00368 if (ValueCell == HCELL_NIL) return FALSE; 00369 00370 /* Read the start value */ 00371 Value = HvGetCell(Hive, ValueCell); 00372 ASSERT(Value); 00373 Data = (PLONG)CmpValueToData(Hive, Value, &Length); 00374 ASSERT(Data); 00375 00376 /* Return if the type matches */ 00377 return (*Data == LoadType); 00378 } 00379 00380 BOOLEAN 00381 NTAPI 00382 INIT_FUNCTION 00383 CmpFindDrivers(IN PHHIVE Hive, 00384 IN HCELL_INDEX ControlSet, 00385 IN SERVICE_LOAD_TYPE LoadType, 00386 IN PWCHAR BootFileSystem OPTIONAL, 00387 IN PLIST_ENTRY DriverListHead) 00388 { 00389 HCELL_INDEX ServicesCell, ControlCell, GroupOrderCell, DriverCell; 00390 HCELL_INDEX SafeBootCell = HCELL_NIL; 00391 UNICODE_STRING Name; 00392 ULONG i; 00393 WCHAR Buffer[128]; 00394 UNICODE_STRING UnicodeString, KeyPath; 00395 PBOOT_DRIVER_NODE FsNode; 00396 PCM_KEY_NODE ControlNode, ServicesNode, Node; 00397 ASSERT(Hive->ReleaseCellRoutine == NULL); 00398 00399 /* Open the control set key */ 00400 ControlNode = HvGetCell(Hive, ControlSet); 00401 ASSERT(ControlNode); 00402 00403 /* Get services cell */ 00404 RtlInitUnicodeString(&Name, L"Services"); 00405 ServicesCell = CmpFindSubKeyByName(Hive, ControlNode, &Name); 00406 if (ServicesCell == HCELL_NIL) return FALSE; 00407 00408 /* Open services key */ 00409 ServicesNode = HvGetCell(Hive, ServicesCell); 00410 ASSERT(ServicesNode); 00411 00412 /* Get control cell */ 00413 RtlInitUnicodeString(&Name, L"Control"); 00414 ControlCell = CmpFindSubKeyByName(Hive, ControlNode, &Name); 00415 if (ControlCell == HCELL_NIL) return FALSE; 00416 00417 /* Get the group order cell and read it */ 00418 RtlInitUnicodeString(&Name, L"GroupOrderList"); 00419 Node = HvGetCell(Hive, ControlCell); 00420 ASSERT(Node); 00421 GroupOrderCell = CmpFindSubKeyByName(Hive, Node, &Name); 00422 if (GroupOrderCell == HCELL_NIL) return FALSE; 00423 00424 /* Get Safe Boot cell */ 00425 if(InitSafeBootMode) 00426 { 00427 /* Open the Safe Boot key */ 00428 RtlInitUnicodeString(&Name, L"SafeBoot"); 00429 Node = HvGetCell(Hive, ControlCell); 00430 ASSERT(Node); 00431 SafeBootCell = CmpFindSubKeyByName(Hive, Node, &Name); 00432 if (SafeBootCell == HCELL_NIL) return FALSE; 00433 00434 /* Open the correct start key (depending on the mode) */ 00435 Node = HvGetCell(Hive, SafeBootCell); 00436 ASSERT(Node); 00437 switch(InitSafeBootMode) 00438 { 00439 /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */ 00440 case 1: 00441 case 3: RtlInitUnicodeString(&Name, L"Minimal"); break; 00442 case 2: RtlInitUnicodeString(&Name, L"Network"); break; 00443 default: return FALSE; 00444 } 00445 SafeBootCell = CmpFindSubKeyByName(Hive, Node, &Name); 00446 if(SafeBootCell == HCELL_NIL) return FALSE; 00447 } 00448 00449 /* Build the root registry path */ 00450 RtlInitEmptyUnicodeString(&KeyPath, Buffer, sizeof(Buffer)); 00451 RtlAppendUnicodeToString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); 00452 00453 /* Find the first subkey (ie: the first driver or service) */ 00454 i = 0; 00455 DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, i); 00456 while (DriverCell != HCELL_NIL) 00457 { 00458 /* Make sure it's a driver of this start type AND is "safe" to load */ 00459 if (CmpIsLoadType(Hive, DriverCell, LoadType) && 00460 CmpIsSafe(Hive, SafeBootCell, DriverCell)) 00461 { 00462 /* Add it to the list */ 00463 CmpAddDriverToList(Hive, 00464 DriverCell, 00465 GroupOrderCell, 00466 &KeyPath, 00467 DriverListHead); 00468 00469 } 00470 00471 /* Try the next subkey */ 00472 DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, ++i); 00473 } 00474 00475 /* Check if we have a boot file system */ 00476 if (BootFileSystem) 00477 { 00478 /* Find it */ 00479 RtlInitUnicodeString(&UnicodeString, BootFileSystem); 00480 DriverCell = CmpFindSubKeyByName(Hive, ServicesNode, &UnicodeString); 00481 if (DriverCell != HCELL_NIL) 00482 { 00483 /* Always add it to the list */ 00484 CmpAddDriverToList(Hive, 00485 DriverCell, 00486 GroupOrderCell, 00487 &KeyPath, 00488 DriverListHead); 00489 00490 /* Mark it as critical so it always loads */ 00491 FsNode = CONTAINING_RECORD(DriverListHead->Flink, 00492 BOOT_DRIVER_NODE, 00493 ListEntry.Link); 00494 FsNode->ErrorControl = SERVICE_ERROR_CRITICAL; 00495 } 00496 } 00497 00498 /* We're done! */ 00499 return TRUE; 00500 } 00501 00502 BOOLEAN 00503 NTAPI 00504 INIT_FUNCTION 00505 CmpDoSort(IN PLIST_ENTRY DriverListHead, 00506 IN PUNICODE_STRING OrderList) 00507 { 00508 PWCHAR Current, End = NULL; 00509 PLIST_ENTRY NextEntry; 00510 UNICODE_STRING GroupName; 00511 PBOOT_DRIVER_NODE CurrentNode; 00512 00513 /* We're going from end to start, so get to the last group and keep going */ 00514 Current = &OrderList->Buffer[OrderList->Length / sizeof(WCHAR)]; 00515 while (Current > OrderList->Buffer) 00516 { 00517 /* Scan the current string */ 00518 do 00519 { 00520 if (*Current == UNICODE_NULL) End = Current; 00521 } while ((*(--Current - 1) != UNICODE_NULL) && (Current != OrderList->Buffer)); 00522 00523 /* This is our cleaned up string for this specific group */ 00524 ASSERT(End != NULL); 00525 GroupName.Length = (USHORT)(End - Current) * sizeof(WCHAR); 00526 GroupName.MaximumLength = GroupName.Length; 00527 GroupName.Buffer = Current; 00528 00529 /* Now loop the driver list */ 00530 NextEntry = DriverListHead->Flink; 00531 while (NextEntry != DriverListHead) 00532 { 00533 /* Get this node */ 00534 CurrentNode = CONTAINING_RECORD(NextEntry, 00535 BOOT_DRIVER_NODE, 00536 ListEntry.Link); 00537 00538 /* Get the next entry now since we'll do a relink */ 00539 NextEntry = CurrentNode->ListEntry.Link.Flink; 00540 00541 /* Is there a group name and does it match the current group? */ 00542 if ((CurrentNode->Group.Buffer) && 00543 (RtlEqualUnicodeString(&GroupName, &CurrentNode->Group, TRUE))) 00544 { 00545 /* Remove from this location and re-link in the new one */ 00546 RemoveEntryList(&CurrentNode->ListEntry.Link); 00547 InsertHeadList(DriverListHead, &CurrentNode->ListEntry.Link); 00548 } 00549 } 00550 00551 /* Move on */ 00552 Current--; 00553 } 00554 00555 /* All done */ 00556 return TRUE; 00557 } 00558 00559 BOOLEAN 00560 NTAPI 00561 INIT_FUNCTION 00562 CmpSortDriverList(IN PHHIVE Hive, 00563 IN HCELL_INDEX ControlSet, 00564 IN PLIST_ENTRY DriverListHead) 00565 { 00566 HCELL_INDEX Controls, GroupOrder, ListCell; 00567 UNICODE_STRING Name, DependList; 00568 PCM_KEY_VALUE ListNode; 00569 ULONG Length; 00570 PCM_KEY_NODE Node; 00571 ASSERT(Hive->ReleaseCellRoutine == NULL); 00572 00573 /* Open the control key */ 00574 Node = HvGetCell(Hive, ControlSet); 00575 ASSERT(Node); 00576 RtlInitUnicodeString(&Name, L"Control"); 00577 Controls = CmpFindSubKeyByName(Hive, Node, &Name); 00578 if (Controls == HCELL_NIL) return FALSE; 00579 00580 /* Open the service group order */ 00581 Node = HvGetCell(Hive, Controls); 00582 ASSERT(Node); 00583 RtlInitUnicodeString(&Name, L"ServiceGroupOrder"); 00584 GroupOrder = CmpFindSubKeyByName(Hive, Node, &Name); 00585 if (GroupOrder == HCELL_NIL) return FALSE; 00586 00587 /* Open the list key */ 00588 Node = HvGetCell(Hive, GroupOrder); 00589 ASSERT(Node); 00590 RtlInitUnicodeString(&Name, L"list"); 00591 ListCell = CmpFindValueByName(Hive, Node, &Name); 00592 if (ListCell == HCELL_NIL) return FALSE; 00593 00594 /* Now read the actual list */ 00595 ListNode = HvGetCell(Hive, ListCell); 00596 ASSERT(ListNode); 00597 if (ListNode->Type != REG_MULTI_SZ) return FALSE; 00598 00599 /* Copy it into a buffer */ 00600 DependList.Buffer = (PWCHAR)CmpValueToData(Hive, ListNode, &Length); 00601 if (!DependList.Buffer) return FALSE; 00602 DependList.Length = DependList.MaximumLength = (USHORT)Length - sizeof(UNICODE_NULL); 00603 00604 /* And start the recurive sort algorithm */ 00605 return CmpDoSort(DriverListHead, &DependList); 00606 } 00607 00608 BOOLEAN 00609 NTAPI 00610 INIT_FUNCTION 00611 CmpOrderGroup(IN PBOOT_DRIVER_NODE StartNode, 00612 IN PBOOT_DRIVER_NODE EndNode) 00613 { 00614 PBOOT_DRIVER_NODE CurrentNode, PreviousNode; 00615 PLIST_ENTRY ListEntry; 00616 00617 /* Base case, nothing to do */ 00618 if (StartNode == EndNode) return TRUE; 00619 00620 /* Loop the nodes */ 00621 CurrentNode = StartNode; 00622 do 00623 { 00624 /* Save this as the previous node */ 00625 PreviousNode = CurrentNode; 00626 00627 /* And move to the next one */ 00628 ListEntry = CurrentNode->ListEntry.Link.Flink; 00629 CurrentNode = CONTAINING_RECORD(ListEntry, 00630 BOOT_DRIVER_NODE, 00631 ListEntry.Link); 00632 00633 /* Check if the previous driver had a bigger tag */ 00634 if (PreviousNode->Tag > CurrentNode->Tag) 00635 { 00636 /* Check if we need to update the tail */ 00637 if (CurrentNode == EndNode) 00638 { 00639 /* Update the tail */ 00640 ListEntry = CurrentNode->ListEntry.Link.Blink; 00641 EndNode = CONTAINING_RECORD(ListEntry, 00642 BOOT_DRIVER_NODE, 00643 ListEntry.Link); 00644 } 00645 00646 /* Remove this driver since we need to move it */ 00647 RemoveEntryList(&CurrentNode->ListEntry.Link); 00648 00649 /* Keep looping until we find a driver with a lower tag than ours */ 00650 while ((PreviousNode->Tag > CurrentNode->Tag) && (PreviousNode != StartNode)) 00651 { 00652 /* We'll be re-inserted at this spot */ 00653 ListEntry = PreviousNode->ListEntry.Link.Blink; 00654 PreviousNode = CONTAINING_RECORD(ListEntry, 00655 BOOT_DRIVER_NODE, 00656 ListEntry.Link); 00657 } 00658 00659 /* Do the insert in the new location */ 00660 InsertTailList(&PreviousNode->ListEntry.Link, &CurrentNode->ListEntry.Link); 00661 00662 /* Update the head, if needed */ 00663 if (PreviousNode == StartNode) StartNode = CurrentNode; 00664 } 00665 } while (CurrentNode != EndNode); 00666 00667 /* All done */ 00668 return TRUE; 00669 } 00670 00671 BOOLEAN 00672 NTAPI 00673 INIT_FUNCTION 00674 CmpResolveDriverDependencies(IN PLIST_ENTRY DriverListHead) 00675 { 00676 PLIST_ENTRY NextEntry; 00677 PBOOT_DRIVER_NODE StartNode, EndNode, CurrentNode; 00678 00679 /* Loop the list */ 00680 NextEntry = DriverListHead->Flink; 00681 while (NextEntry != DriverListHead) 00682 { 00683 /* Find the first entry */ 00684 StartNode = CONTAINING_RECORD(NextEntry, 00685 BOOT_DRIVER_NODE, 00686 ListEntry.Link); 00687 do 00688 { 00689 /* Find the last entry */ 00690 EndNode = CONTAINING_RECORD(NextEntry, 00691 BOOT_DRIVER_NODE, 00692 ListEntry.Link); 00693 00694 /* Get the next entry */ 00695 NextEntry = NextEntry->Flink; 00696 CurrentNode = CONTAINING_RECORD(NextEntry, 00697 BOOT_DRIVER_NODE, 00698 ListEntry.Link); 00699 00700 /* If the next entry is back to the top, break out */ 00701 if (NextEntry == DriverListHead) break; 00702 00703 /* Otherwise, check if this entry is equal */ 00704 if (!RtlEqualUnicodeString(&StartNode->Group, 00705 &CurrentNode->Group, 00706 TRUE)) 00707 { 00708 /* It is, so we've detected a cycle, break out */ 00709 break; 00710 } 00711 } while (NextEntry != DriverListHead); 00712 00713 /* Now we have the correct start and end pointers, so do the sort */ 00714 CmpOrderGroup(StartNode, EndNode); 00715 } 00716 00717 /* We're done */ 00718 return TRUE; 00719 } 00720 00721 BOOLEAN 00722 NTAPI 00723 INIT_FUNCTION 00724 CmpIsSafe(IN PHHIVE Hive, 00725 IN HCELL_INDEX SafeBootCell, 00726 IN HCELL_INDEX DriverCell) 00727 { 00728 PCM_KEY_NODE SafeBootNode; 00729 PCM_KEY_NODE DriverNode; 00730 PCM_KEY_VALUE KeyValue; 00731 HCELL_INDEX CellIndex; 00732 ULONG Length = 0; 00733 UNICODE_STRING Name; 00734 PWCHAR OriginalName; 00735 ASSERT(Hive->ReleaseCellRoutine == NULL); 00736 00737 /* Driver key node (mandatory) */ 00738 ASSERT(DriverCell != HCELL_NIL); 00739 DriverNode = HvGetCell(Hive, DriverCell); 00740 ASSERT(DriverNode); 00741 00742 /* Safe boot key node (optional but return TRUE if not present) */ 00743 if(SafeBootCell == HCELL_NIL) return TRUE; 00744 SafeBootNode = HvGetCell(Hive, SafeBootCell); 00745 if(!SafeBootNode) return FALSE; 00746 00747 /* Search by the name from the group */ 00748 RtlInitUnicodeString(&Name, L"Group"); 00749 CellIndex = CmpFindValueByName(Hive, DriverNode, &Name); 00750 if(CellIndex != HCELL_NIL) 00751 { 00752 KeyValue = HvGetCell(Hive, CellIndex); 00753 ASSERT(KeyValue); 00754 if (KeyValue->Type == REG_SZ || KeyValue->Type == REG_EXPAND_SZ) 00755 { 00756 /* Compose the search 'key' */ 00757 Name.Buffer = (PWCHAR)CmpValueToData(Hive, KeyValue, &Length); 00758 if (!Name.Buffer) return FALSE; 00759 Name.Length = (USHORT)Length - sizeof(UNICODE_NULL); 00760 Name.MaximumLength = Name.Length; 00761 /* Search for corresponding key in the Safe Boot key */ 00762 CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name); 00763 if(CellIndex != HCELL_NIL) return TRUE; 00764 } 00765 } 00766 00767 /* Group has not been found - find driver name */ 00768 Name.Length = DriverNode->Flags & KEY_COMP_NAME ? 00769 CmpCompressedNameSize(DriverNode->Name, 00770 DriverNode->NameLength) : 00771 DriverNode->NameLength; 00772 Name.MaximumLength = Name.Length; 00773 /* Now allocate the buffer for it and copy the name */ 00774 Name.Buffer = CmpAllocate(Name.Length, FALSE, TAG_CM); 00775 if (!Name.Buffer) return FALSE; 00776 if (DriverNode->Flags & KEY_COMP_NAME) 00777 { 00778 /* Compressed name */ 00779 CmpCopyCompressedName(Name.Buffer, 00780 Name.Length, 00781 DriverNode->Name, 00782 DriverNode->NameLength); 00783 } 00784 else 00785 { 00786 /* Normal name */ 00787 RtlCopyMemory(Name.Buffer, DriverNode->Name, DriverNode->NameLength); 00788 } 00789 CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name); 00790 RtlFreeUnicodeString(&Name); 00791 if(CellIndex != HCELL_NIL) return TRUE; 00792 00793 /* Not group or driver name - search by image name */ 00794 RtlInitUnicodeString(&Name, L"ImagePath"); 00795 CellIndex = CmpFindValueByName(Hive, DriverNode, &Name); 00796 if(CellIndex != HCELL_NIL) 00797 { 00798 KeyValue = HvGetCell(Hive, CellIndex); 00799 ASSERT(KeyValue); 00800 if (KeyValue->Type == REG_SZ || KeyValue->Type == REG_EXPAND_SZ) 00801 { 00802 /* Compose the search 'key' */ 00803 OriginalName = (PWCHAR)CmpValueToData(Hive, KeyValue, &Length); 00804 if (!OriginalName) return FALSE; 00805 /* Get the base image file name */ 00806 Name.Buffer = wcsrchr(OriginalName, L'\\'); 00807 if (!Name.Buffer) return FALSE; 00808 ++Name.Buffer; 00809 /* Length of the base name must be >=1 */ 00810 Name.Length = (USHORT)Length - (USHORT)((PUCHAR)Name.Buffer - (PUCHAR)OriginalName) 00811 - sizeof(UNICODE_NULL); 00812 if(Name.Length < 1) return FALSE; 00813 Name.MaximumLength = Name.Length; 00814 /* Search for corresponding key in the Safe Boot key */ 00815 CellIndex = CmpFindSubKeyByName(Hive, SafeBootNode, &Name); 00816 if(CellIndex != HCELL_NIL) return TRUE; 00817 } 00818 } 00819 /* Nothing found - nothing else to search */ 00820 return FALSE; 00821 } 00822 00823 /* EOF */ Generated on Sun May 27 2012 04:37:05 for ReactOS by
1.7.6.1
|