Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cmboot.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 00005 Module Name: 00006 00007 cmboot.c 00008 00009 Abstract: 00010 00011 This provides routines for determining driver load lists from the 00012 registry. The relevant drivers are extracted from the registry, 00013 sorted by groups, and then dependencies are resolved. 00014 00015 This module is used both by the OS Loader for determining the boot 00016 driver list (CmScanRegistry) and by IoInitSystem for determining 00017 the drivers to be loaded in Phase 1 Initialization 00018 (CmGetSystemDriverList) 00019 00020 Author: 00021 00022 John Vert (jvert) 7-Apr-1992 00023 00024 Environment: 00025 00026 OS Loader environment 00027 or 00028 kernel mode 00029 00030 Revision History: 00031 00032 --*/ 00033 #include "cmp.h" 00034 #include <profiles.h> 00035 00036 #define LOAD_LAST 0xffffffff 00037 #define LOAD_NEXT_TO_LAST (LOAD_LAST-1) 00038 00039 // 00040 // Private function prototypes. 00041 // 00042 BOOLEAN 00043 CmpAddDriverToList( 00044 IN PHHIVE Hive, 00045 IN HCELL_INDEX DriverCell, 00046 IN HCELL_INDEX GroupOrderCell, 00047 IN PUNICODE_STRING RegistryPath, 00048 IN PLIST_ENTRY BootDriverListHead 00049 ); 00050 00051 BOOLEAN 00052 CmpDoSort( 00053 IN PLIST_ENTRY DriverListHead, 00054 IN PUNICODE_STRING OrderList 00055 ); 00056 00057 ULONG 00058 CmpFindTagIndex( 00059 IN PHHIVE Hive, 00060 IN HCELL_INDEX TagCell, 00061 IN HCELL_INDEX GroupOrderCell, 00062 IN PUNICODE_STRING GroupName 00063 ); 00064 00065 BOOLEAN 00066 CmpIsLoadType( 00067 IN PHHIVE Hive, 00068 IN HCELL_INDEX Cell, 00069 IN SERVICE_LOAD_TYPE LoadType 00070 ); 00071 00072 BOOLEAN 00073 CmpOrderGroup( 00074 IN PBOOT_DRIVER_NODE GroupStart, 00075 IN PBOOT_DRIVER_NODE GroupEnd 00076 ); 00077 00078 #define CmpValueToData(Hive,Value,realsize) \ 00079 (CmpIsHKeyValueSmall(realsize,Value->DataLength) ? \ 00080 ((struct _CELL_DATA *)(&Value->Data)) : HvGetCell(Hive,Value->Data)) 00081 00082 VOID 00083 BlPrint( 00084 PCHAR cp, 00085 ... 00086 ); 00087 00088 #ifdef ALLOC_PRAGMA 00089 #pragma alloc_text(INIT,CmpFindNLSData) 00090 #pragma alloc_text(INIT,CmpFindDrivers) 00091 #pragma alloc_text(INIT,CmpIsLoadType) 00092 #pragma alloc_text(INIT,CmpAddDriverToList) 00093 #pragma alloc_text(INIT,CmpSortDriverList) 00094 #pragma alloc_text(INIT,CmpDoSort) 00095 #pragma alloc_text(INIT,CmpResolveDriverDependencies) 00096 #pragma alloc_text(INIT,CmpSetCurrentProfile) 00097 #pragma alloc_text(INIT,CmpOrderGroup) 00098 #pragma alloc_text(INIT,CmpFindControlSet) 00099 #pragma alloc_text(INIT,CmpFindTagIndex) 00100 #pragma alloc_text(INIT,CmpFindProfileOption) 00101 #ifdef _WANT_MACHINE_IDENTIFICATION 00102 #pragma alloc_text(INIT,CmpGetBiosDateFromRegistry) 00103 #endif 00104 #endif 00105 00106 00107 BOOLEAN 00108 CmpFindNLSData( 00109 IN PHHIVE Hive, 00110 IN HCELL_INDEX ControlSet, 00111 OUT PUNICODE_STRING AnsiFilename, 00112 OUT PUNICODE_STRING OemFilename, 00113 OUT PUNICODE_STRING CaseTableFilename, 00114 OUT PUNICODE_STRING OemHalFont 00115 ) 00116 00117 /*++ 00118 00119 Routine Description: 00120 00121 Traverses a particular control set and determines the filenames for 00122 the NLS data files that need to be loaded. 00123 00124 Arguments: 00125 00126 Hive - Supplies the hive control structure for the SYSTEM hive. 00127 00128 ControlSet - Supplies the HCELL_INDEX of the root of the control set. 00129 00130 AnsiFileName - Returns the name of the Ansi codepage file (c_1252.nls) 00131 00132 OemFileName - Returns the name of the OEM codepage file (c_437.nls) 00133 00134 CaseTableFileName - Returns the name of the Unicode upper/lowercase 00135 table for the language (l_intl.nls) 00136 00137 OemHalfont - Returns the name of the font file to be used by the HAL. 00138 00139 Return Value: 00140 00141 TRUE - filenames successfully determined 00142 00143 FALSE - hive is corrupt 00144 00145 --*/ 00146 00147 { 00148 UNICODE_STRING Name; 00149 HCELL_INDEX Control; 00150 HCELL_INDEX Nls; 00151 HCELL_INDEX CodePage; 00152 HCELL_INDEX Language; 00153 HCELL_INDEX ValueCell; 00154 PHCELL_INDEX Index; 00155 PCM_KEY_VALUE Value; 00156 NTSTATUS Status; 00157 ULONG realsize; 00158 00159 // 00160 // Find CONTROL node 00161 // 00162 RtlInitUnicodeString(&Name, L"Control"); 00163 Control = CmpFindSubKeyByName(Hive, 00164 (PCM_KEY_NODE)HvGetCell(Hive,ControlSet), 00165 &Name); 00166 if (Control == HCELL_NIL) { 00167 return(FALSE); 00168 } 00169 00170 // 00171 // Find NLS node 00172 // 00173 RtlInitUnicodeString(&Name, L"NLS"); 00174 Nls = CmpFindSubKeyByName(Hive, 00175 (PCM_KEY_NODE)HvGetCell(Hive,Control), 00176 &Name); 00177 if (Nls == HCELL_NIL) { 00178 return(FALSE); 00179 } 00180 00181 // 00182 // Find CodePage node 00183 // 00184 RtlInitUnicodeString(&Name, L"CodePage"); 00185 CodePage = CmpFindSubKeyByName(Hive, 00186 (PCM_KEY_NODE)HvGetCell(Hive,Nls), 00187 &Name); 00188 if (CodePage == HCELL_NIL) { 00189 return(FALSE); 00190 } 00191 00192 // 00193 // Find ACP value 00194 // 00195 RtlInitUnicodeString(&Name, L"ACP"); 00196 ValueCell = CmpFindValueByName(Hive, 00197 (PCM_KEY_NODE)HvGetCell(Hive,CodePage), 00198 &Name); 00199 if (ValueCell == HCELL_NIL) { 00200 return(FALSE); 00201 } 00202 00203 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00204 Name.Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize); 00205 Name.MaximumLength=(USHORT)realsize; 00206 Name.Length = 0; 00207 while ((Name.Length<Name.MaximumLength) && 00208 (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) { 00209 Name.Length += sizeof(WCHAR); 00210 } 00211 00212 // 00213 // Find ACP filename 00214 // 00215 ValueCell = CmpFindValueByName(Hive, 00216 (PCM_KEY_NODE)HvGetCell(Hive,CodePage), 00217 &Name); 00218 if (ValueCell == HCELL_NIL) { 00219 return(FALSE); 00220 } 00221 00222 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00223 AnsiFilename->Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize); 00224 AnsiFilename->Length = AnsiFilename->MaximumLength = (USHORT)realsize; 00225 00226 // 00227 // Find OEMCP node 00228 // 00229 RtlInitUnicodeString(&Name, L"OEMCP"); 00230 ValueCell = CmpFindValueByName(Hive, 00231 (PCM_KEY_NODE)HvGetCell(Hive,CodePage), 00232 &Name); 00233 if (ValueCell == HCELL_NIL) { 00234 return(FALSE); 00235 } 00236 00237 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00238 Name.Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize); 00239 Name.MaximumLength = (USHORT)realsize; 00240 Name.Length = 0; 00241 while ((Name.Length<Name.MaximumLength) && 00242 (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) { 00243 Name.Length += sizeof(WCHAR); 00244 } 00245 00246 // 00247 // Find OEMCP filename 00248 // 00249 ValueCell = CmpFindValueByName(Hive, 00250 (PCM_KEY_NODE)HvGetCell(Hive,CodePage), 00251 &Name); 00252 if (ValueCell == HCELL_NIL) { 00253 return(FALSE); 00254 } 00255 00256 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00257 OemFilename->Buffer = (PWSTR)CmpValueToData(Hive, Value,realsize); 00258 OemFilename->Length = OemFilename->MaximumLength = (USHORT)realsize; 00259 00260 // 00261 // Find Language node 00262 // 00263 RtlInitUnicodeString(&Name, L"Language"); 00264 Language = CmpFindSubKeyByName(Hive, 00265 (PCM_KEY_NODE)HvGetCell(Hive,Nls), 00266 &Name); 00267 if (Language == HCELL_NIL) { 00268 return(FALSE); 00269 } 00270 00271 // 00272 // Find Default value 00273 // 00274 RtlInitUnicodeString(&Name, L"Default"); 00275 ValueCell = CmpFindValueByName(Hive, 00276 (PCM_KEY_NODE)HvGetCell(Hive,Language), 00277 &Name); 00278 if (ValueCell == HCELL_NIL) { 00279 return(FALSE); 00280 } 00281 00282 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00283 Name.Buffer = (PWSTR)CmpValueToData(Hive, Value,realsize); 00284 Name.MaximumLength = (USHORT)realsize; 00285 Name.Length = 0; 00286 00287 while ((Name.Length<Name.MaximumLength) && 00288 (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) { 00289 Name.Length+=sizeof(WCHAR); 00290 } 00291 00292 // 00293 // Find default filename 00294 // 00295 ValueCell = CmpFindValueByName(Hive, 00296 (PCM_KEY_NODE)HvGetCell(Hive,Language), 00297 &Name); 00298 if (ValueCell == HCELL_NIL) { 00299 return(FALSE); 00300 } 00301 00302 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00303 CaseTableFilename->Buffer = (PWSTR)CmpValueToData(Hive, Value,realsize); 00304 CaseTableFilename->Length = CaseTableFilename->MaximumLength = (USHORT)realsize; 00305 00306 // 00307 // Find OEMHAL filename 00308 // 00309 RtlInitUnicodeString(&Name, L"OEMHAL"); 00310 ValueCell = CmpFindValueByName(Hive, 00311 (PCM_KEY_NODE)HvGetCell(Hive,CodePage), 00312 &Name); 00313 if (ValueCell == HCELL_NIL) { 00314 #ifdef i386 00315 OemHalFont->Buffer = NULL; 00316 OemHalFont->Length = 0; 00317 OemHalFont->MaximumLength = 0; 00318 return TRUE; 00319 #endif 00320 return(FALSE); 00321 } 00322 00323 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00324 OemHalFont->Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize); 00325 OemHalFont->Length = (USHORT)realsize; 00326 OemHalFont->MaximumLength = (USHORT)realsize; 00327 00328 return(TRUE); 00329 } 00330 00331 00332 BOOLEAN 00333 CmpFindDrivers( 00334 IN PHHIVE Hive, 00335 IN HCELL_INDEX ControlSet, 00336 IN SERVICE_LOAD_TYPE LoadType, 00337 IN PWSTR BootFileSystem OPTIONAL, 00338 IN PLIST_ENTRY DriverListHead 00339 ) 00340 00341 /*++ 00342 00343 Routine Description: 00344 00345 Traverses a particular control set and creates a list of boot drivers 00346 to be loaded. This list is unordered, but complete. 00347 00348 Arguments: 00349 00350 Hive - Supplies the hive control structure for the SYSTEM hive. 00351 00352 ControlSet - Supplies the HCELL_INDEX of the root of the control set. 00353 00354 LoadType - Supplies the type of drivers to be loaded (BootLoad, 00355 SystemLoad, AutoLoad, etc) 00356 00357 BootFileSystem - If present, supplies the base name of the boot 00358 filesystem, which is explicitly added to the driver list. 00359 00360 DriverListHead - Supplies a pointer to the head of the (empty) list 00361 of boot drivers to load. 00362 00363 Return Value: 00364 00365 TRUE - List successfully created. 00366 00367 FALSE - Hive is corrupt. 00368 00369 --*/ 00370 00371 { 00372 HCELL_INDEX Services; 00373 HCELL_INDEX Control; 00374 HCELL_INDEX GroupOrder; 00375 HCELL_INDEX DriverCell; 00376 UNICODE_STRING Name; 00377 PHCELL_INDEX Index; 00378 int i; 00379 UNICODE_STRING UnicodeString; 00380 UNICODE_STRING BasePath; 00381 WCHAR BaseBuffer[128]; 00382 PBOOT_DRIVER_NODE BootFileSystemNode; 00383 PCM_KEY_NODE ControlNode; 00384 PCM_KEY_NODE ServicesNode; 00385 00386 // 00387 // Find SERVICES node. 00388 // 00389 ControlNode = (PCM_KEY_NODE)HvGetCell(Hive,ControlSet); 00390 RtlInitUnicodeString(&Name, L"Services"); 00391 Services = CmpFindSubKeyByName(Hive, 00392 ControlNode, 00393 &Name); 00394 if (Services == HCELL_NIL) { 00395 return(FALSE); 00396 } 00397 ServicesNode = (PCM_KEY_NODE)HvGetCell(Hive,Services); 00398 00399 // 00400 // Find CONTROL node. 00401 // 00402 RtlInitUnicodeString(&Name, L"Control"); 00403 Control = CmpFindSubKeyByName(Hive, 00404 ControlNode, 00405 &Name); 00406 if (Control == HCELL_NIL) { 00407 return(FALSE); 00408 } 00409 00410 // 00411 // Find GroupOrderList node. 00412 // 00413 RtlInitUnicodeString(&Name, L"GroupOrderList"); 00414 GroupOrder = CmpFindSubKeyByName(Hive, 00415 (PCM_KEY_NODE)HvGetCell(Hive,Control), 00416 &Name); 00417 if (GroupOrder == HCELL_NIL) { 00418 return(FALSE); 00419 } 00420 00421 BasePath.Length = 0; 00422 BasePath.MaximumLength = sizeof(BaseBuffer); 00423 BasePath.Buffer = BaseBuffer; 00424 RtlAppendUnicodeToString(&BasePath, L"\\Registry\\Machine\\System\\"); 00425 RtlAppendUnicodeToString(&BasePath, L"CurrentControlSet\\Services\\"); 00426 00427 i=0; 00428 do { 00429 DriverCell = CmpFindSubKeyByNumber(Hive,ServicesNode,i++); 00430 if (DriverCell != HCELL_NIL) { 00431 if (CmpIsLoadType(Hive, DriverCell, LoadType)) { 00432 CmpAddDriverToList(Hive, 00433 DriverCell, 00434 GroupOrder, 00435 &BasePath, 00436 DriverListHead); 00437 00438 } 00439 } 00440 } while ( DriverCell != HCELL_NIL ); 00441 00442 if (ARGUMENT_PRESENT(BootFileSystem)) { 00443 // 00444 // Add boot filesystem to boot driver list 00445 // 00446 00447 RtlInitUnicodeString(&UnicodeString, BootFileSystem); 00448 DriverCell = CmpFindSubKeyByName(Hive, 00449 ServicesNode, 00450 &UnicodeString); 00451 if (DriverCell != HCELL_NIL) { 00452 CmpAddDriverToList(Hive, 00453 DriverCell, 00454 GroupOrder, 00455 &BasePath, 00456 DriverListHead); 00457 00458 // 00459 // mark the Boot Filesystem critical 00460 // 00461 BootFileSystemNode = CONTAINING_RECORD(DriverListHead->Flink, 00462 BOOT_DRIVER_NODE, 00463 ListEntry.Link); 00464 BootFileSystemNode->ErrorControl = SERVICE_ERROR_CRITICAL; 00465 } 00466 } 00467 return(TRUE); 00468 00469 } 00470 00471 00472 BOOLEAN 00473 CmpIsLoadType( 00474 IN PHHIVE Hive, 00475 IN HCELL_INDEX Cell, 00476 IN SERVICE_LOAD_TYPE LoadType 00477 ) 00478 00479 /*++ 00480 00481 Routine Description: 00482 00483 Determines if the driver is of a specified LoadType, based on its 00484 node values. 00485 00486 Arguments: 00487 00488 Hive - Supplies a pointer to the hive control structure for the system 00489 hive. 00490 00491 Cell - Supplies the cell index of the driver's node in the system hive. 00492 00493 LoadType - Supplies the type of drivers to be loaded (BootLoad, 00494 SystemLoad, AutoLoad, etc) 00495 00496 Return Value: 00497 00498 TRUE - Driver is the correct type and should be loaded. 00499 00500 FALSE - Driver is not the correct type and should not be loaded. 00501 00502 --*/ 00503 00504 { 00505 HCELL_INDEX ValueCell; 00506 PLONG Data; 00507 PHCELL_INDEX Index; 00508 UNICODE_STRING Name; 00509 PCM_KEY_VALUE Value; 00510 NTSTATUS Status; 00511 ULONG realsize; 00512 00513 // 00514 // Must have a Start=BootLoad value in order to be a boot driver, so 00515 // look for that first. 00516 // 00517 RtlInitUnicodeString(&Name, L"Start"); 00518 ValueCell = CmpFindValueByName(Hive, 00519 (PCM_KEY_NODE)HvGetCell(Hive,Cell), 00520 &Name); 00521 if (ValueCell == HCELL_NIL) { 00522 return(FALSE); 00523 } 00524 00525 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00526 00527 Data = (PLONG)CmpValueToData(Hive,Value,realsize); 00528 00529 if (*Data != LoadType) { 00530 return(FALSE); 00531 } 00532 00533 return(TRUE); 00534 } 00535 00536 00537 BOOLEAN 00538 CmpAddDriverToList( 00539 IN PHHIVE Hive, 00540 IN HCELL_INDEX DriverCell, 00541 IN HCELL_INDEX GroupOrderCell, 00542 IN PUNICODE_STRING RegistryPath, 00543 IN PLIST_ENTRY BootDriverListHead 00544 ) 00545 00546 /*++ 00547 00548 Routine Description: 00549 00550 This routine allocates a list entry node for a particular driver. 00551 It initializes it with the registry path, filename, group name, and 00552 dependency list. Finally, it inserts the new node into the boot 00553 driver list. 00554 00555 Note that this routine allocates memory by calling the Hive's 00556 memory allocation procedure. 00557 00558 Arguments: 00559 00560 Hive - Supplies a pointer to the hive control structure 00561 00562 DriverCell - Supplies the HCELL_INDEX of the driver's node in the hive. 00563 00564 GroupOrderCell - Supplies the HCELL_INDEX of the GroupOrderList key. 00565 ( \Registry\Machine\System\CurrentControlSet\Control\GroupOrderList ) 00566 00567 RegistryPath - Supplies the full registry path to the SERVICES node 00568 of the current control set. 00569 00570 BootDriverListHead - Supplies the head of the boot driver list 00571 00572 Return Value: 00573 00574 TRUE - Driver successfully added to boot driver list. 00575 00576 FALSE - Could not add driver to boot driver list. 00577 00578 --*/ 00579 00580 { 00581 PCM_KEY_NODE Driver; 00582 USHORT DriverNameLength; 00583 PCM_KEY_VALUE Value; 00584 PBOOT_DRIVER_NODE DriverNode; 00585 PBOOT_DRIVER_LIST_ENTRY DriverEntry; 00586 HCELL_INDEX ValueCell; 00587 HCELL_INDEX Tag; 00588 UNICODE_STRING UnicodeString; 00589 PUNICODE_STRING FileName; 00590 NTSTATUS Status; 00591 ULONG Length; 00592 PHCELL_INDEX Index; 00593 ULONG realsize; 00594 00595 Driver = (PCM_KEY_NODE)HvGetCell(Hive, DriverCell); 00596 DriverNode = (Hive->Allocate)(sizeof(BOOT_DRIVER_NODE),FALSE); 00597 if (DriverNode == NULL) { 00598 return(FALSE); 00599 } 00600 if (Driver->Flags & KEY_COMP_NAME) { 00601 DriverNode->Name.Length = CmpCompressedNameSize(Driver->Name,Driver->NameLength); 00602 DriverNode->Name.Buffer = (Hive->Allocate)(DriverNode->Name.Length, FALSE); 00603 if (DriverNode->Name.Buffer == NULL) { 00604 return(FALSE); 00605 } 00606 CmpCopyCompressedName(DriverNode->Name.Buffer, 00607 DriverNode->Name.Length, 00608 Driver->Name, 00609 Driver->NameLength); 00610 00611 } else { 00612 DriverNode->Name.Length = Driver->NameLength; 00613 DriverNode->Name.Buffer = Driver->Name; 00614 } 00615 DriverNode->Name.MaximumLength = DriverNode->Name.Length; 00616 DriverNameLength = DriverNode->Name.Length; 00617 00618 DriverEntry = &DriverNode->ListEntry; 00619 00620 // 00621 // Check for ImagePath value, which will override the default name 00622 // if it is present. 00623 // 00624 RtlInitUnicodeString(&UnicodeString, L"ImagePath"); 00625 ValueCell = CmpFindValueByName(Hive, 00626 (PCM_KEY_NODE)HvGetCell(Hive,DriverCell), 00627 &UnicodeString); 00628 if (ValueCell == HCELL_NIL) { 00629 00630 // 00631 // No ImagePath, so generate default filename. 00632 // Build up Unicode filename ("system32\drivers<nodename>.sys"); 00633 // 00634 00635 Length = sizeof(L"System32\\Drivers\\") + 00636 DriverNameLength + 00637 sizeof(L".sys"); 00638 00639 FileName = &DriverEntry->FilePath; 00640 FileName->Length = 0; 00641 FileName->MaximumLength = (USHORT)Length; 00642 FileName->Buffer = (PWSTR)(Hive->Allocate)(Length, FALSE); 00643 if (FileName->Buffer == NULL) { 00644 return(FALSE); 00645 } 00646 if (!NT_SUCCESS(RtlAppendUnicodeToString(FileName, L"System32\\"))) { 00647 return(FALSE); 00648 } 00649 if (!NT_SUCCESS(RtlAppendUnicodeToString(FileName, L"Drivers\\"))) { 00650 return(FALSE); 00651 } 00652 if (!NT_SUCCESS( 00653 RtlAppendUnicodeStringToString(FileName, 00654 &DriverNode->Name))) { 00655 return(FALSE); 00656 } 00657 if (!NT_SUCCESS(RtlAppendUnicodeToString(FileName, L".sys"))) { 00658 return(FALSE); 00659 } 00660 00661 } else { 00662 Value = (PCM_KEY_VALUE)HvGetCell(Hive,ValueCell); 00663 FileName = &DriverEntry->FilePath; 00664 FileName->Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize); 00665 FileName->MaximumLength = FileName->Length = (USHORT)realsize; 00666 } 00667 00668 FileName = &DriverEntry->RegistryPath; 00669 FileName->Length = 0; 00670 FileName->MaximumLength = RegistryPath->Length + DriverNameLength; 00671 FileName->Buffer = (Hive->Allocate)(FileName->MaximumLength,FALSE); 00672 if (FileName->Buffer == NULL) { 00673 return(FALSE); 00674 } 00675 RtlAppendUnicodeStringToString(FileName, RegistryPath); 00676 RtlAppendUnicodeStringToString(FileName, &DriverNode->Name); 00677 00678 InsertHeadList(BootDriverListHead, &DriverEntry->Link); 00679 00680 // 00681 // Find "ErrorControl" value 00682 // 00683 00684 RtlInitUnicodeString(&UnicodeString, L"ErrorControl"); 00685 ValueCell = CmpFindValueByName(Hive, 00686 (PCM_KEY_NODE)HvGetCell(Hive,DriverCell), 00687 &UnicodeString); 00688 if (ValueCell == HCELL_NIL) { 00689 DriverNode->ErrorControl = NormalError; 00690 } else { 00691 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00692 DriverNode->ErrorControl = *(PULONG)CmpValueToData(Hive,Value,realsize); 00693 } 00694 00695 // 00696 // Find "Group" value 00697 // 00698 RtlInitUnicodeString(&UnicodeString, L"group"); 00699 ValueCell = CmpFindValueByName(Hive, 00700 (PCM_KEY_NODE)HvGetCell(Hive,DriverCell), 00701 &UnicodeString); 00702 if (ValueCell == HCELL_NIL) { 00703 DriverNode->Group.Length = 0; 00704 DriverNode->Group.MaximumLength = 0; 00705 DriverNode->Group.Buffer = NULL; 00706 } else { 00707 Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell); 00708 DriverNode->Group.Buffer = (PWSTR)CmpValueToData(Hive,Value,realsize); 00709 DriverNode->Group.Length = (USHORT)realsize - sizeof(WCHAR); 00710 DriverNode->Group.MaximumLength = (USHORT)DriverNode->Group.Length; 00711 } 00712 00713 // 00714 // Calculate the tag value for the driver. If the driver has no tag, 00715 // this defaults to 0xffffffff, so the driver is loaded last in the 00716 // group. 00717 // 00718 RtlInitUnicodeString(&UnicodeString, L"Tag"); 00719 Tag = CmpFindValueByName(Hive, 00720 (PCM_KEY_NODE)HvGetCell(Hive,DriverCell), 00721 &UnicodeString); 00722 if (Tag == HCELL_NIL) { 00723 DriverNode->Tag = LOAD_LAST; 00724 } else { 00725 // 00726 // Now we have to find this tag in the tag list for the group. 00727 // If the tag is not in the tag list, then it defaults to 0xfffffffe, 00728 // so it is loaded after all the drivers in the tag list, but before 00729 // all the drivers without tags at all. 00730 // 00731 00732 DriverNode->Tag = CmpFindTagIndex(Hive, 00733 Tag, 00734 GroupOrderCell, 00735 &DriverNode->Group); 00736 } 00737 00738 return(TRUE); 00739 00740 } 00741 00742 00743 BOOLEAN 00744 CmpSortDriverList( 00745 IN PHHIVE Hive, 00746 IN HCELL_INDEX ControlSet, 00747 IN PLIST_ENTRY DriverListHead 00748 ) 00749 00750 /*++ 00751 00752 Routine Description: 00753 00754 Sorts the list of boot drivers by their groups based on the group 00755 ordering in <control_set>\CONTROL\SERVICE_GROUP_ORDER:list 00756 00757 Does NOT do dependency ordering. 00758 00759 Arguments: 00760 00761 Hive - Supplies the hive control structure for the SYSTEM hive. 00762 00763 ControlSet - Supplies the HCELL_INDEX of the root of the control set. 00764 00765 DriverListHead - Supplies a pointer to the head of the list of 00766 boot drivers to be sorted. 00767 00768 Return Value: 00769 00770 TRUE - List successfully sorted 00771 00772 FALSE - List is inconsistent and could not be sorted. 00773 00774 --*/ 00775 00776 { 00777 HCELL_INDEX Controls; 00778 HCELL_INDEX GroupOrder; 00779 HCELL_INDEX ListCell; 00780 UNICODE_STRING Name; 00781 UNICODE_STRING DependList; 00782 PHCELL_INDEX Index; 00783 NTSTATUS Status; 00784 PCM_KEY_VALUE ListNode; 00785 ULONG realsize; 00786 00787 // 00788 // Find "CONTROL" node. 00789 // 00790 RtlInitUnicodeString(&Name, L"Control"); 00791 Controls = CmpFindSubKeyByName(Hive, 00792 (PCM_KEY_NODE)HvGetCell(Hive,ControlSet), 00793 &Name); 00794 if (Controls == HCELL_NIL) { 00795 return(FALSE); 00796 } 00797 00798 // 00799 // Find "SERVICE_GROUP_ORDER" subkey 00800 // 00801 RtlInitUnicodeString(&Name, L"ServiceGroupOrder"); 00802 GroupOrder = CmpFindSubKeyByName(Hive, 00803 (PCM_KEY_NODE)HvGetCell(Hive,Controls), 00804 &Name); 00805 if (GroupOrder == HCELL_NIL) { 00806 return(FALSE); 00807 } 00808 00809 // 00810 // Find "list" value 00811 // 00812 RtlInitUnicodeString(&Name, L"list"); 00813 ListCell = CmpFindValueByName(Hive, 00814 (PCM_KEY_NODE)HvGetCell(Hive,GroupOrder), 00815 &Name); 00816 if (ListCell == HCELL_NIL) { 00817 return(FALSE); 00818 } 00819 ListNode = (PCM_KEY_VALUE)HvGetCell(Hive, ListCell); 00820 if (ListNode->Type != REG_MULTI_SZ) { 00821 return(FALSE); 00822 } 00823 00824 DependList.Buffer = (PWSTR)CmpValueToData(Hive,ListNode,realsize); 00825 DependList.Length = DependList.MaximumLength = (USHORT)realsize - sizeof(WCHAR); 00826 00827 // 00828 // Dependency list is now pointed to by DependList->Buffer. We need 00829 // to sort the driver entry list. 00830 // 00831 00832 return (CmpDoSort(DriverListHead, &DependList)); 00833 00834 } 00835 00836 BOOLEAN 00837 CmpDoSort( 00838 IN PLIST_ENTRY DriverListHead, 00839 IN PUNICODE_STRING OrderList 00840 ) 00841 00842 /*++ 00843 00844 Routine Description: 00845 00846 Sorts the boot driver list based on the order list 00847 00848 Start with the last entry in the group order list and work towards 00849 the beginning. For each group entry, move all driver entries that 00850 are members of the group to the front of the list. Driver entries 00851 with no groups, or with a group that does not match any in the 00852 group list will be shoved to the end of the list. 00853 00854 Arguments: 00855 00856 DriverListHead - Supplies a pointer to the head of the list of 00857 boot drivers to be sorted. 00858 00859 OrderList - Supplies pointer to the order list 00860 00861 Return Value: 00862 00863 TRUE - List successfully ordered 00864 00865 FALSE - List is inconsistent and could not be ordered. 00866 00867 --*/ 00868 00869 { 00870 PWSTR Current; 00871 PWSTR End; 00872 PLIST_ENTRY Next; 00873 PBOOT_DRIVER_NODE CurrentNode; 00874 UNICODE_STRING CurrentGroup; 00875 00876 00877 Current = (PWSTR) ((PUCHAR)(OrderList->Buffer)+OrderList->Length); 00878 00879 while (Current > OrderList->Buffer) { 00880 do { 00881 if (*(Current) == UNICODE_NULL) { 00882 End = Current; 00883 } 00884 --Current; 00885 } while ((*(Current-1) != UNICODE_NULL) && 00886 ( Current != OrderList->Buffer)); 00887 00888 // 00889 // Current now points to the beginning of the NULL-terminated 00890 // Unicode string. 00891 // End now points to the end of the string 00892 // 00893 CurrentGroup.Length = (USHORT) ((PCHAR)End - (PCHAR)Current); 00894 CurrentGroup.MaximumLength = CurrentGroup.Length; 00895 CurrentGroup.Buffer = Current; 00896 Next = DriverListHead->Flink; 00897 while (Next != DriverListHead) { 00898 CurrentNode = CONTAINING_RECORD(Next, 00899 BOOT_DRIVER_NODE, 00900 ListEntry.Link); 00901 Next = CurrentNode->ListEntry.Link.Flink; 00902 if (CurrentNode->Group.Buffer != NULL) { 00903 if (RtlEqualUnicodeString(&CurrentGroup, &CurrentNode->Group,TRUE)) { 00904 RemoveEntryList(&CurrentNode->ListEntry.Link); 00905 InsertHeadList(DriverListHead, 00906 &CurrentNode->ListEntry.Link); 00907 } 00908 } 00909 } 00910 --Current; 00911 00912 } 00913 00914 return(TRUE); 00915 00916 } 00917 00918 00919 BOOLEAN 00920 CmpResolveDriverDependencies( 00921 IN PLIST_ENTRY DriverListHead 00922 ) 00923 00924 /*++ 00925 00926 Routine Description: 00927 00928 This routine orders driver nodes in a group based on their dependencies 00929 on one another. It removes any drivers that have circular dependencies 00930 from the list. 00931 00932 Arguments: 00933 00934 DriverListHead - Supplies a pointer to the head of the list of 00935 boot drivers to be sorted. 00936 00937 Return Value: 00938 00939 TRUE - Dependencies successfully resolved 00940 00941 FALSE - Corrupt hive. 00942 00943 --*/ 00944 00945 { 00946 PLIST_ENTRY CurrentEntry; 00947 PBOOT_DRIVER_NODE GroupStart; 00948 PBOOT_DRIVER_NODE GroupEnd; 00949 PBOOT_DRIVER_NODE CurrentNode; 00950 00951 CurrentEntry = DriverListHead->Flink; 00952 00953 while (CurrentEntry != DriverListHead) { 00954 // 00955 // The list is already ordered by groups. Find the first and 00956 // last entry in each group, and order each of these sub-lists 00957 // based on their dependencies. 00958 // 00959 00960 GroupStart = CONTAINING_RECORD(CurrentEntry, 00961 BOOT_DRIVER_NODE, 00962 ListEntry.Link); 00963 do { 00964 GroupEnd = CONTAINING_RECORD(CurrentEntry, 00965 BOOT_DRIVER_NODE, 00966 ListEntry.Link); 00967 00968 CurrentEntry = CurrentEntry->Flink; 00969 CurrentNode = CONTAINING_RECORD(CurrentEntry, 00970 BOOT_DRIVER_NODE, 00971 ListEntry.Link); 00972 00973 if (CurrentEntry == DriverListHead) { 00974 break; 00975 } 00976 00977 if (!RtlEqualUnicodeString(&GroupStart->Group, 00978 &CurrentNode->Group, 00979 TRUE)) { 00980 break; 00981 } 00982 00983 } while ( CurrentEntry != DriverListHead ); 00984 00985 // 00986 // GroupStart now points to the first driver node in the group, 00987 // and GroupEnd points to the last driver node in the group. 00988 // 00989 CmpOrderGroup(GroupStart, GroupEnd); 00990 00991 } 00992 return(TRUE); 00993 } 00994 00995 00996 BOOLEAN 00997 CmpOrderGroup( 00998 IN PBOOT_DRIVER_NODE GroupStart, 00999 IN PBOOT_DRIVER_NODE GroupEnd 01000 ) 01001 01002 /*++ 01003 01004 Routine Description: 01005 01006 Reorders the nodes in a driver group based on their tag values. 01007 01008 Arguments: 01009 01010 GroupStart - Supplies the first node in the group. 01011 01012 GroupEnd - Supplies the last node in the group. 01013 01014 Return Value: 01015 01016 TRUE - Group successfully reordered 01017 01018 FALSE - Circular dependencies detected. 01019 01020 --*/ 01021 01022 { 01023 PBOOT_DRIVER_NODE Current; 01024 PBOOT_DRIVER_NODE Previous; 01025 PLIST_ENTRY ListEntry; 01026 BOOLEAN StartOver=FALSE; 01027 01028 if (GroupStart == GroupEnd) { 01029 return(TRUE); 01030 } 01031 01032 Current = GroupStart; 01033 01034 do { 01035 // 01036 // If the driver before the current one has a lower tag, then 01037 // we do not need to move it. If not, then remove the driver 01038 // from the list and scan backwards until we find a driver with 01039 // a tag that is <= the current tag, or we reach the beginning 01040 // of the list. 01041 // 01042 Previous = Current; 01043 ListEntry = Current->ListEntry.Link.Flink; 01044 Current = CONTAINING_RECORD(ListEntry, 01045 BOOT_DRIVER_NODE, 01046 ListEntry.Link); 01047 01048 if (Previous->Tag > Current->Tag) { 01049 // 01050 // Remove the Current driver from the list, and search 01051 // backwards until we find a tag that is <= the current 01052 // driver's tag. Reinsert the current driver there. 01053 // 01054 if (Current == GroupEnd) { 01055 ListEntry = Current->ListEntry.Link.Blink; 01056 GroupEnd = CONTAINING_RECORD(ListEntry, 01057 BOOT_DRIVER_NODE, 01058 ListEntry.Link); 01059 } 01060 RemoveEntryList(&Current->ListEntry.Link); 01061 while ( (Previous->Tag > Current->Tag) && 01062 (Previous != GroupStart) ) { 01063 ListEntry = Previous->ListEntry.Link.Blink; 01064 Previous = CONTAINING_RECORD(ListEntry, 01065 BOOT_DRIVER_NODE, 01066 ListEntry.Link); 01067 } 01068 InsertTailList(&Previous->ListEntry.Link, 01069 &Current->ListEntry.Link); 01070 if (Previous == GroupStart) { 01071 GroupStart = Current; 01072 } 01073 } 01074 01075 } while ( Current != GroupEnd ); 01076 01077 return(TRUE); 01078 } 01079 01080 01081 HCELL_INDEX 01082 CmpFindControlSet( 01083 IN PHHIVE SystemHive, 01084 IN HCELL_INDEX RootCell, 01085 IN PUNICODE_STRING SelectName, 01086 OUT PBOOLEAN AutoSelect 01087 ) 01088 01089 /*++ 01090 01091 Routine Description: 01092 01093 This routines parses the SYSTEM hive and "Select" node 01094 to locate the control set to be used for booting. 01095 01096 Note that this routines also updates the value of Current to reflect 01097 the control set that was just found. This is what we want to do 01098 when this is called during boot. During I/O initialization, this 01099 is irrelevant, since we're just changing it to what it already is. 01100 01101 Arguments: 01102 01103 SystemHive - Supplies the hive control structure for the SYSTEM hive. 01104 01105 RootCell - Supplies the HCELL_INDEX of the root cell of the hive. 01106 01107 SelectName - Supplies the name of the Select value to be used in 01108 determining the control set. This should be one of "Current" 01109 "Default" or "LastKnownGood" 01110 01111 AutoSelect - Returns the value of the AutoSelect value under 01112 the Select node. 01113 01114 Return Value: 01115 01116 != HCELL_NIL - Cell Index of the control set to be used for booting. 01117 == HCELL_NIL - Indicates the hive is corrupt or inconsistent 01118 01119 --*/ 01120 01121 { 01122 HCELL_INDEX Select; 01123 HCELL_INDEX ValueCell; 01124 HCELL_INDEX ControlSet; 01125 HCELL_INDEX AutoSelectCell; 01126 NTSTATUS Status; 01127 UNICODE_STRING Name; 01128 ANSI_STRING AnsiString; 01129 PHCELL_INDEX Index; 01130 PCM_KEY_VALUE Value; 01131 PULONG ControlSetIndex; 01132 PULONG CurrentControl; 01133 CHAR AsciiBuffer[128]; 01134 WCHAR UnicodeBuffer[128]; 01135 ULONG realsize; 01136 01137 // 01138 // Find \SYSTEM\SELECT node. 01139 // 01140 RtlInitUnicodeString(&Name, L"select"); 01141 Select = CmpFindSubKeyByName(SystemHive, 01142 (PCM_KEY_NODE)HvGetCell(SystemHive,RootCell), 01143 &Name); 01144 if (Select == HCELL_NIL) { 01145 return(HCELL_NIL); 01146 } 01147 01148 // 01149 // Find AutoSelect value 01150 // 01151 RtlInitUnicodeString(&Name, L"AutoSelect"); 01152 AutoSelectCell = CmpFindValueByName(SystemHive, 01153 (PCM_KEY_NODE)HvGetCell(SystemHive,Select), 01154 &Name); 01155 if (AutoSelectCell == HCELL_NIL) { 01156 // 01157 // It's not there, we don't care. Set autoselect to TRUE 01158 // 01159 *AutoSelect = TRUE; 01160 } else { 01161 Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell); 01162 *AutoSelect = *(PBOOLEAN)(CmpValueToData(SystemHive,Value,realsize)); 01163 } 01164 01165 ValueCell = CmpFindValueByName(SystemHive, 01166 (PCM_KEY_NODE)HvGetCell(SystemHive,Select), 01167 SelectName); 01168 if (ValueCell == HCELL_NIL) { 01169 return(HCELL_NIL); 01170 } 01171 Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01172 if (Value->Type != REG_DWORD) { 01173 return(HCELL_NIL); 01174 } 01175 01176 ControlSetIndex = (PULONG)CmpValueToData(SystemHive, Value,realsize); 01177 01178 // 01179 // Find appropriate control set 01180 // 01181 01182 sprintf(AsciiBuffer, "ControlSet%03d", *ControlSetIndex); 01183 AnsiString.Length = AnsiString.MaximumLength = strlen(&(AsciiBuffer[0])); 01184 AnsiString.Buffer = AsciiBuffer; 01185 Name.MaximumLength = 128*sizeof(WCHAR); 01186 Name.Buffer = UnicodeBuffer; 01187 Status = RtlAnsiStringToUnicodeString(&Name, 01188 &AnsiString, 01189 FALSE); 01190 if (!NT_SUCCESS(Status)) { 01191 return(HCELL_NIL); 01192 } 01193 ControlSet = CmpFindSubKeyByName(SystemHive, 01194 (PCM_KEY_NODE)HvGetCell(SystemHive,RootCell), 01195 &Name); 01196 if (ControlSet == HCELL_NIL) { 01197 return(HCELL_NIL); 01198 } 01199 01200 // 01201 // Control set was successfully found, so update the value in "Current" 01202 // to reflect the control set we are going to use. 01203 // 01204 RtlInitUnicodeString(&Name, L"Current"); 01205 ValueCell = CmpFindValueByName(SystemHive, 01206 (PCM_KEY_NODE)HvGetCell(SystemHive,Select), 01207 &Name); 01208 if (ValueCell != HCELL_NIL) { 01209 Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01210 if (Value->Type == REG_DWORD) { 01211 CurrentControl = (PULONG)CmpValueToData(SystemHive, Value,realsize); 01212 *CurrentControl = *ControlSetIndex; 01213 } 01214 } 01215 return(ControlSet); 01216 01217 } 01218 01219 01220 VOID 01221 CmpSetCurrentProfile( 01222 IN PHHIVE Hive, 01223 IN HCELL_INDEX ControlSet, 01224 IN PCM_HARDWARE_PROFILE Profile 01225 ) 01226 01227 /*++ 01228 01229 Routine Description: 01230 01231 Edits the in-memory copy of the registry to reflect the hardware 01232 profile that the system is booting from. 01233 01234 Arguments: 01235 01236 Hive - Supplies a pointer to the hive control structure 01237 01238 ControlSet - Supplies the HCELL_INDEX of the current control set. 01239 01240 Profile - Supplies a pointer to the selected hardware profile 01241 01242 Return Value: 01243 01244 None. 01245 01246 --*/ 01247 01248 { 01249 HCELL_INDEX IDConfigDB; 01250 PCM_KEY_NODE IDConfigNode; 01251 HCELL_INDEX CurrentConfigCell; 01252 PCM_KEY_VALUE CurrentConfigValue; 01253 UNICODE_STRING Name; 01254 PULONG CurrentConfig; 01255 ULONG realsize; 01256 01257 IDConfigDB = CmpFindProfileOption(Hive, 01258 ControlSet, 01259 NULL, 01260 NULL, 01261 NULL); 01262 if (IDConfigDB != HCELL_NIL) { 01263 IDConfigNode = (PCM_KEY_NODE)HvGetCell(Hive, IDConfigDB); 01264 RtlInitUnicodeString(&Name, L"CurrentConfig"); 01265 CurrentConfigCell = CmpFindValueByName(Hive, 01266 IDConfigNode, 01267 &Name); 01268 if (CurrentConfigCell != HCELL_NIL) { 01269 CurrentConfigValue = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentConfigCell); 01270 if (CurrentConfigValue->Type == REG_DWORD) { 01271 CurrentConfig = (PULONG)CmpValueToData(Hive, 01272 CurrentConfigValue, 01273 realsize); 01274 *CurrentConfig = Profile->Id; 01275 } 01276 } 01277 } 01278 01279 01280 } 01281 01282 01283 HCELL_INDEX 01284 CmpFindProfileOption( 01285 IN PHHIVE SystemHive, 01286 IN HCELL_INDEX ControlSet, 01287 OUT OPTIONAL PCM_HARDWARE_PROFILE_LIST *ReturnedProfileList, 01288 OUT OPTIONAL PCM_HARDWARE_PROFILE_ALIAS_LIST *ReturnedAliasList, 01289 OUT OPTIONAL PULONG ProfileTimeout 01290 ) 01291 01292 /*++ 01293 01294 Routine Description: 01295 01296 This routines parses the SYSTEM hive and locates the 01297 "CurrentControlSet\Control\IDConfigDB" node to determine the 01298 hardware profile configuration settings. 01299 01300 Arguments: 01301 01302 SystemHive - Supplies the hive control structure for the SYSTEM hive. 01303 01304 ControlSet - Supplies the HCELL_INDEX of the root cell of the hive. 01305 01306 ProfileList - Returns the list of available hardware profiles sorted 01307 by preference. Will be allocated by this routine if 01308 NULL is passed in, or a pointer to a CM_HARDWARE_PROFILE_LIST 01309 structure that is too small is passed in. 01310 01311 ProfileTimeout - Returns the timeout value for the config menu. 01312 01313 Return Value: 01314 01315 != HCELL_NIL - Cell Index of the IDConfigDB node. 01316 == HCELL_NIL - Indicates IDConfigDB does not exist 01317 01318 --*/ 01319 { 01320 HCELL_INDEX ControlCell; 01321 HCELL_INDEX IDConfigDB; 01322 HCELL_INDEX DefaultCell; 01323 HCELL_INDEX TimeoutCell; 01324 HCELL_INDEX ProfileCell; 01325 HCELL_INDEX AliasCell; 01326 HCELL_INDEX HWCell; 01327 PCM_KEY_NODE HWNode; 01328 PCM_KEY_NODE ProfileNode; 01329 PCM_KEY_NODE AliasNode; 01330 PCM_KEY_NODE ConfigDBNode; 01331 PCM_KEY_NODE Control; 01332 PCM_KEY_VALUE TimeoutValue; 01333 UNICODE_STRING Name; 01334 ULONG realsize; 01335 PCM_HARDWARE_PROFILE_LIST ProfileList; 01336 PCM_HARDWARE_PROFILE_ALIAS_LIST AliasList; 01337 ULONG ProfileCount; 01338 ULONG AliasCount; 01339 ULONG i,j; 01340 WCHAR NameBuf[20]; 01341 01342 // 01343 // Find Control node 01344 // 01345 RtlInitUnicodeString(&Name, L"Control"); 01346 ControlCell = CmpFindSubKeyByName(SystemHive, 01347 (PCM_KEY_NODE)HvGetCell(SystemHive,ControlSet), 01348 &Name); 01349 if (ControlCell == HCELL_NIL) { 01350 return(HCELL_NIL); 01351 } 01352 Control = (PCM_KEY_NODE)HvGetCell(SystemHive, ControlCell); 01353 01354 // 01355 // Find IDConfigDB node 01356 // 01357 RtlInitUnicodeString(&Name, L"IDConfigDB"); 01358 IDConfigDB = CmpFindSubKeyByName(SystemHive, 01359 Control, 01360 &Name); 01361 if (IDConfigDB == HCELL_NIL) { 01362 return(HCELL_NIL); 01363 } 01364 ConfigDBNode = (PCM_KEY_NODE)HvGetCell(SystemHive, IDConfigDB); 01365 01366 if (ARGUMENT_PRESENT(ProfileTimeout)) { 01367 // 01368 // Find UserWaitInterval value. This is the timeout 01369 // 01370 RtlInitUnicodeString(&Name, L"UserWaitInterval"); 01371 TimeoutCell = CmpFindValueByName(SystemHive, 01372 ConfigDBNode, 01373 &Name); 01374 if (TimeoutCell == HCELL_NIL) { 01375 *ProfileTimeout = 0; 01376 } else { 01377 TimeoutValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, TimeoutCell); 01378 if (TimeoutValue->Type != REG_DWORD) { 01379 *ProfileTimeout = 0; 01380 } else { 01381 *ProfileTimeout = *(PULONG)CmpValueToData(SystemHive, TimeoutValue, realsize); 01382 } 01383 } 01384 } 01385 01386 if (ARGUMENT_PRESENT(ReturnedProfileList)) { 01387 ProfileList = *ReturnedProfileList; 01388 // 01389 // Enumerate the keys under IDConfigDB\Hardware Profiles 01390 // and build the list of available hardware profiles. The list 01391 // is built sorted by PreferenceOrder. Therefore, when the 01392 // list is complete, the default hardware profile is at the 01393 // head of the list. 01394 // 01395 RtlInitUnicodeString(&Name, L"Hardware Profiles"); 01396 ProfileCell = CmpFindSubKeyByName(SystemHive, 01397 ConfigDBNode, 01398 &Name); 01399 if (ProfileCell == HCELL_NIL) { 01400 ProfileCount = 0; 01401 if (ProfileList != NULL) { 01402 ProfileList->CurrentProfileCount = 0; 01403 } 01404 } else { 01405 ProfileNode = (PCM_KEY_NODE)HvGetCell(SystemHive, ProfileCell); 01406 ProfileCount = ProfileNode->SubKeyCounts[Stable]; 01407 if ((ProfileList == NULL) || (ProfileList->MaxProfileCount < ProfileCount)) { 01408 // 01409 // Allocate a larger ProfileList 01410 // 01411 ProfileList = (SystemHive->Allocate)(sizeof(CM_HARDWARE_PROFILE_LIST) 01412 + (ProfileCount-1) * sizeof(CM_HARDWARE_PROFILE), 01413 FALSE); 01414 if (ProfileList == NULL) { 01415 return(HCELL_NIL); 01416 } 01417 ProfileList->MaxProfileCount = ProfileCount; 01418 } 01419 ProfileList->CurrentProfileCount = 0; 01420 01421 // 01422 // Enumerate the keys and fill in the profile list. 01423 // 01424 for (i=0; i<ProfileCount; i++) { 01425 CM_HARDWARE_PROFILE TempProfile; 01426 HCELL_INDEX ValueCell; 01427 PCM_KEY_VALUE ValueNode; 01428 UNICODE_STRING KeyName; 01429 ULONG realsize; 01430 01431 HWCell = CmpFindSubKeyByNumber(SystemHive, ProfileNode, i); 01432 if (HWCell == HCELL_NIL) { 01433 // 01434 // This should never happen. 01435 // 01436 ProfileList->CurrentProfileCount = i; 01437 break; 01438 } 01439 HWNode = (PCM_KEY_NODE)HvGetCell(SystemHive, HWCell); 01440 if (HWNode->Flags & KEY_COMP_NAME) { 01441 KeyName.Length = CmpCompressedNameSize(HWNode->Name, 01442 HWNode->NameLength); 01443 KeyName.MaximumLength = sizeof(NameBuf); 01444 if (KeyName.MaximumLength < KeyName.Length) { 01445 KeyName.Length = KeyName.MaximumLength; 01446 } 01447 KeyName.Buffer = NameBuf; 01448 CmpCopyCompressedName(KeyName.Buffer, 01449 KeyName.Length, 01450 HWNode->Name, 01451 HWNode->NameLength); 01452 } else { 01453 KeyName.Length = KeyName.MaximumLength = HWNode->NameLength; 01454 KeyName.Buffer = HWNode->Name; 01455 } 01456 01457 // 01458 // Fill in the temporary profile structure with this 01459 // profile's data. 01460 // 01461 RtlUnicodeStringToInteger(&KeyName, 0, &TempProfile.Id); 01462 RtlInitUnicodeString(&Name, CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER); 01463 ValueCell = CmpFindValueByName(SystemHive, 01464 HWNode, 01465 &Name); 01466 if (ValueCell == HCELL_NIL) { 01467 TempProfile.PreferenceOrder = (ULONG)-1; 01468 } else { 01469 ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01470 TempProfile.PreferenceOrder = *(PULONG)CmpValueToData(SystemHive, 01471 ValueNode, 01472 realsize); 01473 } 01474 RtlInitUnicodeString(&Name, CM_HARDWARE_PROFILE_STR_FRIENDLY_NAME); 01475 ValueCell = CmpFindValueByName(SystemHive, 01476 HWNode, 01477 &Name); 01478 if (ValueCell == HCELL_NIL) { 01479 TempProfile.FriendlyName = L"-------"; 01480 TempProfile.NameLength = wcslen(TempProfile.FriendlyName) * sizeof(WCHAR); 01481 } else { 01482 ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01483 TempProfile.FriendlyName = (PWSTR)CmpValueToData(SystemHive, 01484 ValueNode, 01485 realsize); 01486 TempProfile.NameLength = realsize - sizeof(WCHAR); 01487 } 01488 01489 TempProfile.Flags = 0; 01490 01491 RtlInitUnicodeString(&Name, CM_HARDWARE_PROFILE_STR_ALIASABLE); 01492 ValueCell = CmpFindValueByName(SystemHive, 01493 HWNode, 01494 &Name); 01495 if (ValueCell == HCELL_NIL) { 01496 TempProfile.Flags = CM_HP_FLAGS_ALIASABLE; 01497 } else { 01498 ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01499 01500 if (*(PULONG)CmpValueToData (SystemHive, 01501 ValueNode, 01502 realsize)) { 01503 TempProfile.Flags = CM_HP_FLAGS_ALIASABLE; 01504 // NO other flags set. 01505 } 01506 } 01507 01508 RtlInitUnicodeString(&Name, CM_HARDWARE_PROFILE_STR_PRISTINE); 01509 ValueCell = CmpFindValueByName(SystemHive, 01510 HWNode, 01511 &Name); 01512 if (ValueCell != HCELL_NIL) { 01513 01514 ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01515 01516 if (*(PULONG)CmpValueToData (SystemHive, 01517 ValueNode, 01518 realsize)) { 01519 TempProfile.Flags = CM_HP_FLAGS_PRISTINE; 01520 // NO other flags set. 01521 } 01522 } 01523 01524 // 01525 // If we see a profile with the ID of zero (AKA an illegal) 01526 // ID for a hardware profile to possess, then we know that this 01527 // must be a pristine profile. 01528 // 01529 if (0 == TempProfile.Id) { 01530 TempProfile.Flags = CM_HP_FLAGS_PRISTINE; 01531 // NO other flags set. 01532 01533 TempProfile.PreferenceOrder = -1; // move to the end of the list. 01534 } 01535 01536 01537 // 01538 // Insert this new profile into the appropriate spot in the 01539 // profile array. Entries are sorted by preference order. 01540 // 01541 for (j=0; j<ProfileList->CurrentProfileCount; j++) { 01542 if (ProfileList->Profile[j].PreferenceOrder >= TempProfile.PreferenceOrder) { 01543 // 01544 // Insert at position j. 01545 // 01546 RtlMoveMemory(&ProfileList->Profile[j+1], 01547 &ProfileList->Profile[j], 01548 sizeof(CM_HARDWARE_PROFILE)*(ProfileList->MaxProfileCount-j-1)); 01549 break; 01550 } 01551 } 01552 ProfileList->Profile[j] = TempProfile; 01553 ++ProfileList->CurrentProfileCount; 01554 } 01555 } 01556 *ReturnedProfileList = ProfileList; 01557 } 01558 01559 if (ARGUMENT_PRESENT(ReturnedAliasList)) { 01560 AliasList = *ReturnedAliasList; 01561 // 01562 // Enumerate the keys under IDConfigDB\Alias 01563 // and build the list of available hardware profiles aliases. 01564 // So that if we know our docking state we can find it in the alias 01565 // table. 01566 // 01567 RtlInitUnicodeString(&Name, L"Alias"); 01568 AliasCell = CmpFindSubKeyByName(SystemHive, 01569 ConfigDBNode, 01570 &Name); 01571 if (AliasCell == HCELL_NIL) { 01572 AliasCount = 0; 01573 if (AliasList != NULL) { 01574 AliasList->CurrentAliasCount = 0; 01575 } 01576 } else { 01577 AliasNode = (PCM_KEY_NODE)HvGetCell(SystemHive, AliasCell); 01578 AliasCount = AliasNode->SubKeyCounts[Stable]; 01579 if ((AliasList == NULL) || (AliasList->MaxAliasCount < AliasCount)) { 01580 // 01581 // Allocate a larger AliasList 01582 // 01583 AliasList = (SystemHive->Allocate)(sizeof(CM_HARDWARE_PROFILE_LIST) 01584 + (AliasCount-1) * sizeof(CM_HARDWARE_PROFILE), 01585 FALSE); 01586 if (AliasList == NULL) { 01587 return(HCELL_NIL); 01588 } 01589 AliasList->MaxAliasCount = AliasCount; 01590 } 01591 AliasList->CurrentAliasCount = 0; 01592 01593 // 01594 // Enumerate the keys and fill in the profile list. 01595 // 01596 for (i=0; i<AliasCount; i++) { 01597 #define TempAlias AliasList->Alias[i] 01598 HCELL_INDEX ValueCell; 01599 PCM_KEY_VALUE ValueNode; 01600 UNICODE_STRING KeyName; 01601 ULONG realsize; 01602 01603 HWCell = CmpFindSubKeyByNumber(SystemHive, AliasNode, i); 01604 if (HWCell == HCELL_NIL) { 01605 // 01606 // This should never happen. 01607 // 01608 AliasList->CurrentAliasCount = i; 01609 break; 01610 } 01611 HWNode = (PCM_KEY_NODE)HvGetCell(SystemHive, HWCell); 01612 if (HWNode->Flags & KEY_COMP_NAME) { 01613 KeyName.Length = CmpCompressedNameSize(HWNode->Name, 01614 HWNode->NameLength); 01615 KeyName.MaximumLength = sizeof(NameBuf); 01616 if (KeyName.MaximumLength < KeyName.Length) { 01617 KeyName.Length = KeyName.MaximumLength; 01618 } 01619 KeyName.Buffer = NameBuf; 01620 CmpCopyCompressedName(KeyName.Buffer, 01621 KeyName.Length, 01622 HWNode->Name, 01623 HWNode->NameLength); 01624 } else { 01625 KeyName.Length = KeyName.MaximumLength = HWNode->NameLength; 01626 KeyName.Buffer = HWNode->Name; 01627 } 01628 01629 // 01630 // Fill in the temporary profile structure with this 01631 // profile's data. 01632 // 01633 RtlInitUnicodeString(&Name, L"ProfileNumber"); 01634 ValueCell = CmpFindValueByName(SystemHive, 01635 HWNode, 01636 &Name); 01637 if (ValueCell == HCELL_NIL) { 01638 TempAlias.ProfileNumber = 0; 01639 } else { 01640 ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01641 TempAlias.ProfileNumber = *(PULONG)CmpValueToData(SystemHive, 01642 ValueNode, 01643 realsize); 01644 } 01645 RtlInitUnicodeString(&Name, L"DockState"); 01646 ValueCell = CmpFindValueByName(SystemHive, 01647 HWNode, 01648 &Name); 01649 if (ValueCell == HCELL_NIL) { 01650 TempAlias.DockState = 0; 01651 } else { 01652 ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01653 TempAlias.DockState = *(PULONG)CmpValueToData(SystemHive, 01654 ValueNode, 01655 realsize); 01656 } 01657 RtlInitUnicodeString(&Name, L"DockID"); 01658 ValueCell = CmpFindValueByName(SystemHive, 01659 HWNode, 01660 &Name); 01661 if (ValueCell == HCELL_NIL) { 01662 TempAlias.DockID = 0; 01663 } else { 01664 ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01665 TempAlias.DockID = *(PULONG)CmpValueToData(SystemHive, 01666 ValueNode, 01667 realsize); 01668 } 01669 RtlInitUnicodeString(&Name, L"SerialNumber"); 01670 ValueCell = CmpFindValueByName(SystemHive, 01671 HWNode, 01672 &Name); 01673 if (ValueCell == HCELL_NIL) { 01674 TempAlias.SerialNumber = 0; 01675 } else { 01676 ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell); 01677 TempAlias.SerialNumber = *(PULONG)CmpValueToData(SystemHive, 01678 ValueNode, 01679 realsize); 01680 } 01681 01682 ++AliasList->CurrentAliasCount; 01683 } 01684 } 01685 *ReturnedAliasList = AliasList; 01686 } 01687 01688 return(IDConfigDB); 01689 } 01690 01691 01692 ULONG 01693 CmpFindTagIndex( 01694 IN PHHIVE Hive, 01695 IN HCELL_INDEX TagCell, 01696 IN HCELL_INDEX GroupOrderCell, 01697 IN PUNICODE_STRING GroupName 01698 ) 01699 01700 /*++ 01701 01702 Routine Description: 01703 01704 Calculates the tag index for a driver based on its tag value and 01705 the GroupOrderList entry for its group. 01706 01707 Arguments: 01708 01709 Hive - Supplies the hive control structure for the driver. 01710 01711 TagCell - Supplies the cell index of the driver's tag value cell. 01712 01713 GroupOrderCell - Supplies the cell index for the control set's 01714 GroupOrderList: 01715 01716 \Registry\Machine\System\CurrentControlSet\Control\GroupOrderList 01717 01718 GroupName - Supplies the name of the group the driver belongs to. 01719 Note that if a driver's group does not have an entry under 01720 GroupOrderList, its tags will be ignored. Also note that if 01721 a driver belongs to no group (GroupName is NULL) its tags will 01722 be ignored. 01723 01724 Return Value: 01725 01726 The index that the driver should be sorted by. 01727 01728 --*/ 01729 01730 { 01731 PCM_KEY_VALUE TagValue; 01732 PCM_KEY_VALUE DriverTagValue; 01733 HCELL_INDEX OrderCell; 01734 PULONG OrderVector; 01735 PULONG DriverTag; 01736 NTSTATUS Status; 01737 ULONG CurrentTag; 01738 ULONG realsize; 01739 01740 01741 DriverTagValue = (PCM_KEY_VALUE)HvGetCell(Hive, TagCell); 01742 DriverTag = (PULONG)CmpValueToData(Hive, DriverTagValue, realsize); 01743 01744 OrderCell = CmpFindValueByName(Hive, 01745 (PCM_KEY_NODE)HvGetCell(Hive,GroupOrderCell), 01746 GroupName); 01747 if (OrderCell == HCELL_NIL) { 01748 return(LOAD_NEXT_TO_LAST); 01749 } 01750 01751 TagValue = (PCM_KEY_VALUE)HvGetCell(Hive, OrderCell); 01752 OrderVector = (PULONG)CmpValueToData(Hive, TagValue,realsize); 01753 01754 for (CurrentTag=1; CurrentTag <= OrderVector[0]; CurrentTag++) { 01755 if (OrderVector[CurrentTag] == *DriverTag) { 01756 // 01757 // We have found a matching tag in the OrderVector, so return 01758 // its index. 01759 // 01760 return(CurrentTag); 01761 } 01762 } 01763 01764 // 01765 // There was no matching tag in the OrderVector. 01766 // 01767 return(LOAD_NEXT_TO_LAST); 01768 01769 } 01770 01771 #ifdef _WANT_MACHINE_IDENTIFICATION 01772 01773 BOOLEAN 01774 CmpGetBiosDateFromRegistry( 01775 IN PHHIVE Hive, 01776 IN HCELL_INDEX ControlSet, 01777 OUT PUNICODE_STRING Date 01778 ) 01779 01780 /*++ 01781 01782 Routine Description: 01783 01784 Reads and returns the BIOS date from the registry. 01785 01786 Arguments: 01787 01788 Hive - Supplies the hive control structure for the driver. 01789 01790 ControlSet - Supplies the HCELL_INDEX of the root cell of the hive. 01791 01792 Date - Receives the date string in the format "mm/dd/yy". 01793 01794 Return Value: 01795 01796 TRUE iff successful, else FALSE. 01797 01798 --*/ 01799 01800 { 01801 UNICODE_STRING name; 01802 HCELL_INDEX control; 01803 HCELL_INDEX biosInfo; 01804 HCELL_INDEX valueCell; 01805 PCM_KEY_VALUE value; 01806 ULONG realSize; 01807 01808 // 01809 // Find CONTROL node 01810 // 01811 01812 RtlInitUnicodeString(&name, L"Control"); 01813 control = CmpFindSubKeyByName( Hive, 01814 (PCM_KEY_NODE)HvGetCell(Hive, ControlSet), 01815 &name); 01816 if (control == HCELL_NIL) { 01817 01818 return(FALSE); 01819 } 01820 01821 // 01822 // Find BIOSINFO node 01823 // 01824 01825 RtlInitUnicodeString(&name, L"BIOSINFO"); 01826 biosInfo = CmpFindSubKeyByName( Hive, 01827 (PCM_KEY_NODE)HvGetCell(Hive, control), 01828 &name); 01829 if (biosInfo == HCELL_NIL) { 01830 01831 return(FALSE); 01832 } 01833 01834 // 01835 // Find SystemBiosDate value 01836 // 01837 01838 RtlInitUnicodeString(&name, L"SystemBiosDate"); 01839 valueCell = CmpFindValueByName( Hive, 01840 (PCM_KEY_NODE)HvGetCell(Hive, biosInfo), 01841 &name); 01842 if (valueCell == HCELL_NIL) { 01843 01844 return(FALSE); 01845 } 01846 01847 value = (PCM_KEY_VALUE)HvGetCell(Hive, valueCell); 01848 Date->Buffer = (PWSTR)CmpValueToData(Hive, value, realSize); 01849 Date->MaximumLength=(USHORT)realSize; 01850 Date->Length = 0; 01851 while ( (Date->Length < Date->MaximumLength) && 01852 (Date->Buffer[Date->Length/sizeof(WCHAR)] != UNICODE_NULL)) { 01853 01854 Date->Length += sizeof(WCHAR); 01855 } 01856 01857 return (TRUE); 01858 } 01859 01860 BOOLEAN 01861 CmpGetBiosinfoFileNameFromRegistry( 01862 IN PHHIVE Hive, 01863 IN HCELL_INDEX ControlSet, 01864 OUT PUNICODE_STRING InfName 01865 ) 01866 { 01867 UNICODE_STRING name; 01868 HCELL_INDEX control; 01869 HCELL_INDEX biosInfo; 01870 HCELL_INDEX valueCell; 01871 PCM_KEY_VALUE value; 01872 ULONG realSize; 01873 01874 // 01875 // Find CONTROL node 01876 // 01877 01878 RtlInitUnicodeString(&name, L"Control"); 01879 control = CmpFindSubKeyByName( Hive, 01880 (PCM_KEY_NODE)HvGetCell(Hive, ControlSet), 01881 &name); 01882 if (control == HCELL_NIL) { 01883 01884 return(FALSE); 01885 } 01886 01887 // 01888 // Find BIOSINFO node 01889 // 01890 01891 RtlInitUnicodeString(&name, L"BIOSINFO"); 01892 biosInfo = CmpFindSubKeyByName( Hive, 01893 (PCM_KEY_NODE)HvGetCell(Hive, control), 01894 &name); 01895 if (biosInfo == HCELL_NIL) { 01896 01897 return(FALSE); 01898 } 01899 01900 // 01901 // Find InfName value 01902 // 01903 01904 RtlInitUnicodeString(&name, L"InfName"); 01905 valueCell = CmpFindValueByName( Hive, 01906 (PCM_KEY_NODE)HvGetCell(Hive, biosInfo), 01907 &name); 01908 if (valueCell == HCELL_NIL) { 01909 01910 return(FALSE); 01911 } 01912 01913 value = (PCM_KEY_VALUE)HvGetCell(Hive, valueCell); 01914 InfName->Buffer = (PWSTR)CmpValueToData(Hive, value, realSize); 01915 InfName->MaximumLength=(USHORT)realSize; 01916 InfName->Length = 0; 01917 while ( (InfName->Length < InfName->MaximumLength) && 01918 (InfName->Buffer[InfName->Length/sizeof(WCHAR)] != UNICODE_NULL)) { 01919 01920 InfName->Length += sizeof(WCHAR); 01921 } 01922 01923 return (TRUE); 01924 } 01925 01926 #endif

Generated on Sat May 15 19:39:26 2004 for test by doxygen 1.3.7