Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2805 lines
81 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. cmboot.c
  5. Abstract:
  6. This provides routines for determining driver load lists from the
  7. registry. The relevant drivers are extracted from the registry,
  8. sorted by groups, and then dependencies are resolved.
  9. This module is used both by the OS Loader for determining the boot
  10. driver list (CmScanRegistry) and by IoInitSystem for determining
  11. the drivers to be loaded in Phase 1 Initialization
  12. (CmGetSystemDriverList)
  13. Author:
  14. John Vert (jvert) 7-Apr-1992
  15. Environment:
  16. OS Loader environment
  17. or
  18. kernel mode
  19. Revision History:
  20. --*/
  21. #include "cmp.h"
  22. #include <profiles.h>
  23. #define LOAD_LAST 0xffffffff
  24. #define LOAD_NEXT_TO_LAST (LOAD_LAST-1)
  25. //
  26. // Private function prototypes.
  27. //
  28. BOOLEAN
  29. CmpAddDriverToList(
  30. IN PHHIVE Hive,
  31. IN HCELL_INDEX DriverCell,
  32. IN HCELL_INDEX GroupOrderCell,
  33. IN PUNICODE_STRING RegistryPath,
  34. IN PLIST_ENTRY BootDriverListHead
  35. );
  36. BOOLEAN
  37. CmpDoSort(
  38. IN PLIST_ENTRY DriverListHead,
  39. IN PUNICODE_STRING OrderList
  40. );
  41. ULONG
  42. CmpFindTagIndex(
  43. IN PHHIVE Hive,
  44. IN HCELL_INDEX TagCell,
  45. IN HCELL_INDEX GroupOrderCell,
  46. IN PUNICODE_STRING GroupName
  47. );
  48. BOOLEAN
  49. CmpIsLoadType(
  50. IN PHHIVE Hive,
  51. IN HCELL_INDEX Cell,
  52. IN SERVICE_LOAD_TYPE LoadType
  53. );
  54. BOOLEAN
  55. CmpOrderGroup(
  56. IN PBOOT_DRIVER_NODE GroupStart,
  57. IN PBOOT_DRIVER_NODE GroupEnd
  58. );
  59. VOID
  60. BlPrint(
  61. PCHAR cp,
  62. ...
  63. );
  64. #ifdef ALLOC_PRAGMA
  65. #pragma alloc_text(INIT,CmpFindNLSData)
  66. #pragma alloc_text(INIT,CmpFindDrivers)
  67. #pragma alloc_text(INIT,CmpIsLoadType)
  68. #pragma alloc_text(INIT,CmpAddDriverToList)
  69. #pragma alloc_text(INIT,CmpSortDriverList)
  70. #pragma alloc_text(INIT,CmpDoSort)
  71. #pragma alloc_text(INIT,CmpResolveDriverDependencies)
  72. #pragma alloc_text(INIT,CmpSetCurrentProfile)
  73. #pragma alloc_text(INIT,CmpOrderGroup)
  74. #pragma alloc_text(PAGE,CmpFindControlSet)
  75. #pragma alloc_text(INIT,CmpFindTagIndex)
  76. #pragma alloc_text(INIT,CmpFindProfileOption)
  77. #pragma alloc_text(INIT,CmpValidateSelect)
  78. #ifdef _WANT_MACHINE_IDENTIFICATION
  79. #pragma alloc_text(INIT,CmpGetBiosDateFromRegistry)
  80. #endif
  81. #endif
  82. BOOLEAN
  83. CmpFindNLSData(
  84. IN PHHIVE Hive,
  85. IN HCELL_INDEX ControlSet,
  86. OUT PUNICODE_STRING AnsiFilename,
  87. OUT PUNICODE_STRING OemFilename,
  88. OUT PUNICODE_STRING CaseTableFilename,
  89. OUT PUNICODE_STRING OemHalFont
  90. )
  91. /*++
  92. Routine Description:
  93. Traverses a particular control set and determines the filenames for
  94. the NLS data files that need to be loaded.
  95. Arguments:
  96. Hive - Supplies the hive control structure for the SYSTEM hive.
  97. ControlSet - Supplies the HCELL_INDEX of the root of the control set.
  98. AnsiFileName - Returns the name of the Ansi codepage file (c_1252.nls)
  99. OemFileName - Returns the name of the OEM codepage file (c_437.nls)
  100. CaseTableFileName - Returns the name of the Unicode upper/lowercase
  101. table for the language (l_intl.nls)
  102. OemHalfont - Returns the name of the font file to be used by the HAL.
  103. Return Value:
  104. TRUE - filenames successfully determined
  105. FALSE - hive is corrupt
  106. --*/
  107. {
  108. UNICODE_STRING Name;
  109. HCELL_INDEX Control;
  110. HCELL_INDEX Nls;
  111. HCELL_INDEX CodePage;
  112. HCELL_INDEX Language;
  113. HCELL_INDEX ValueCell;
  114. PHCELL_INDEX Index;
  115. PCM_KEY_VALUE Value;
  116. NTSTATUS Status;
  117. ULONG realsize;
  118. PCM_KEY_NODE Node;
  119. //
  120. // no mapped hives at this point. don't bother releasing cells
  121. //
  122. ASSERT( Hive->ReleaseCellRoutine == NULL );
  123. //
  124. // Find CONTROL node
  125. //
  126. Node = (PCM_KEY_NODE)HvGetCell(Hive,ControlSet);
  127. if( Node == NULL ) {
  128. //
  129. // we couldn't map a view for the bin containing this cell
  130. //
  131. return FALSE;
  132. }
  133. RtlInitUnicodeString(&Name, L"Control");
  134. Control = CmpFindSubKeyByName(Hive,
  135. Node,
  136. &Name);
  137. if (Control == HCELL_NIL) {
  138. return(FALSE);
  139. }
  140. //
  141. // Find NLS node
  142. //
  143. Node = (PCM_KEY_NODE)HvGetCell(Hive,Control);
  144. if( Node == NULL ) {
  145. //
  146. // we couldn't map a view for the bin containing this cell
  147. //
  148. return FALSE;
  149. }
  150. RtlInitUnicodeString(&Name, L"NLS");
  151. Nls = CmpFindSubKeyByName(Hive,
  152. Node,
  153. &Name);
  154. if (Nls == HCELL_NIL) {
  155. return(FALSE);
  156. }
  157. //
  158. // Find CodePage node
  159. //
  160. Node = (PCM_KEY_NODE)HvGetCell(Hive,Nls);
  161. if( Node == NULL ) {
  162. //
  163. // we couldn't map a view for the bin containing this cell
  164. //
  165. return FALSE;
  166. }
  167. RtlInitUnicodeString(&Name, L"CodePage");
  168. CodePage = CmpFindSubKeyByName(Hive,
  169. Node,
  170. &Name);
  171. if (CodePage == HCELL_NIL) {
  172. return(FALSE);
  173. }
  174. //
  175. // Find ACP value
  176. //
  177. Node = (PCM_KEY_NODE)HvGetCell(Hive,CodePage);
  178. if( Node == NULL ) {
  179. //
  180. // we couldn't map a view for the bin containing this cell
  181. //
  182. return FALSE;
  183. }
  184. RtlInitUnicodeString(&Name, L"ACP");
  185. ValueCell = CmpFindValueByName(Hive,
  186. Node,
  187. &Name);
  188. if (ValueCell == HCELL_NIL) {
  189. return(FALSE);
  190. }
  191. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  192. if( Value == NULL ) {
  193. //
  194. // we couldn't map a view for the bin containing this cell
  195. //
  196. return FALSE;
  197. }
  198. Name.Buffer = (PWSTR)CmpValueToData(Hive,Value,&realsize);
  199. if( Name.Buffer == NULL ) {
  200. //
  201. // HvGetCell inside CmpValueToData failed; bail out safely
  202. //
  203. return FALSE;
  204. }
  205. Name.MaximumLength=(USHORT)realsize;
  206. Name.Length = 0;
  207. while ((Name.Length<Name.MaximumLength) &&
  208. (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) {
  209. Name.Length += sizeof(WCHAR);
  210. }
  211. //
  212. // Find ACP filename
  213. //
  214. Node = (PCM_KEY_NODE)HvGetCell(Hive,CodePage);
  215. if( Node == NULL ) {
  216. //
  217. // we couldn't map a view for the bin containing this cell
  218. //
  219. return FALSE;
  220. }
  221. ValueCell = CmpFindValueByName(Hive,
  222. Node,
  223. &Name);
  224. if (ValueCell == HCELL_NIL) {
  225. return(FALSE);
  226. }
  227. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  228. if( Value == NULL ) {
  229. //
  230. // we couldn't map a view for the bin containing this cell
  231. //
  232. return FALSE;
  233. }
  234. AnsiFilename->Buffer = (PWSTR)CmpValueToData(Hive,Value,&realsize);
  235. if( AnsiFilename->Buffer == NULL ) {
  236. //
  237. // HvGetCell inside CmpValueToData failed; bail out safely
  238. //
  239. return FALSE;
  240. }
  241. AnsiFilename->Length = AnsiFilename->MaximumLength = (USHORT)realsize;
  242. //
  243. // Find OEMCP node
  244. //
  245. Node = (PCM_KEY_NODE)HvGetCell(Hive,CodePage);
  246. if( Node == NULL ) {
  247. //
  248. // we couldn't map a view for the bin containing this cell
  249. //
  250. return FALSE;
  251. }
  252. RtlInitUnicodeString(&Name, L"OEMCP");
  253. ValueCell = CmpFindValueByName(Hive,
  254. Node,
  255. &Name);
  256. if (ValueCell == HCELL_NIL) {
  257. return(FALSE);
  258. }
  259. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  260. if( Value == NULL ) {
  261. //
  262. // we couldn't map a view for the bin containing this cell
  263. //
  264. return FALSE;
  265. }
  266. Name.Buffer = (PWSTR)CmpValueToData(Hive,Value,&realsize);
  267. if( Name.Buffer == NULL ) {
  268. //
  269. // HvGetCell inside CmpValueToData failed; bail out safely
  270. //
  271. return FALSE;
  272. }
  273. Name.MaximumLength = (USHORT)realsize;
  274. Name.Length = 0;
  275. while ((Name.Length<Name.MaximumLength) &&
  276. (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) {
  277. Name.Length += sizeof(WCHAR);
  278. }
  279. //
  280. // Find OEMCP filename
  281. //
  282. Node = (PCM_KEY_NODE)HvGetCell(Hive,CodePage);
  283. if( Node == NULL ) {
  284. //
  285. // we couldn't map a view for the bin containing this cell
  286. //
  287. return FALSE;
  288. }
  289. ValueCell = CmpFindValueByName(Hive,
  290. Node,
  291. &Name);
  292. if (ValueCell == HCELL_NIL) {
  293. return(FALSE);
  294. }
  295. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  296. if( Value == NULL ) {
  297. //
  298. // we couldn't map a view for the bin containing this cell
  299. //
  300. return FALSE;
  301. }
  302. OemFilename->Buffer = (PWSTR)CmpValueToData(Hive, Value,&realsize);
  303. if( OemFilename->Buffer == NULL ) {
  304. //
  305. // HvGetCell inside CmpValueToData failed; bail out safely
  306. //
  307. return FALSE;
  308. }
  309. OemFilename->Length = OemFilename->MaximumLength = (USHORT)realsize;
  310. //
  311. // Find Language node
  312. //
  313. Node = (PCM_KEY_NODE)HvGetCell(Hive,Nls);
  314. if( Node == NULL ) {
  315. //
  316. // we couldn't map a view for the bin containing this cell
  317. //
  318. return FALSE;
  319. }
  320. RtlInitUnicodeString(&Name, L"Language");
  321. Language = CmpFindSubKeyByName(Hive,
  322. Node,
  323. &Name);
  324. if (Language == HCELL_NIL) {
  325. return(FALSE);
  326. }
  327. //
  328. // Find Default value
  329. //
  330. Node = (PCM_KEY_NODE)HvGetCell(Hive,Language);
  331. if( Node == NULL ) {
  332. //
  333. // we couldn't map a view for the bin containing this cell
  334. //
  335. return FALSE;
  336. }
  337. RtlInitUnicodeString(&Name, L"Default");
  338. ValueCell = CmpFindValueByName(Hive,
  339. Node,
  340. &Name);
  341. if (ValueCell == HCELL_NIL) {
  342. return(FALSE);
  343. }
  344. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  345. if( Value == NULL ) {
  346. //
  347. // we couldn't map a view for the bin containing this cell
  348. //
  349. return FALSE;
  350. }
  351. Name.Buffer = (PWSTR)CmpValueToData(Hive, Value,&realsize);
  352. if( Name.Buffer == NULL ) {
  353. //
  354. // HvGetCell inside CmpValueToData failed; bail out safely
  355. //
  356. return FALSE;
  357. }
  358. Name.MaximumLength = (USHORT)realsize;
  359. Name.Length = 0;
  360. while ((Name.Length<Name.MaximumLength) &&
  361. (Name.Buffer[Name.Length/sizeof(WCHAR)] != UNICODE_NULL)) {
  362. Name.Length+=sizeof(WCHAR);
  363. }
  364. //
  365. // Find default filename
  366. //
  367. Node = (PCM_KEY_NODE)HvGetCell(Hive,Language);
  368. if( Node == NULL ) {
  369. //
  370. // we couldn't map a view for the bin containing this cell
  371. //
  372. return FALSE;
  373. }
  374. ValueCell = CmpFindValueByName(Hive,
  375. Node,
  376. &Name);
  377. if (ValueCell == HCELL_NIL) {
  378. return(FALSE);
  379. }
  380. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  381. if( Value == NULL ) {
  382. //
  383. // we couldn't map a view for the bin containing this cell
  384. //
  385. return FALSE;
  386. }
  387. CaseTableFilename->Buffer = (PWSTR)CmpValueToData(Hive, Value,&realsize);
  388. if( CaseTableFilename->Buffer == NULL ) {
  389. //
  390. // HvGetCell inside CmpValueToData failed; bail out safely
  391. //
  392. return FALSE;
  393. }
  394. CaseTableFilename->Length = CaseTableFilename->MaximumLength = (USHORT)realsize;
  395. //
  396. // Find OEMHAL filename
  397. //
  398. Node = (PCM_KEY_NODE)HvGetCell(Hive,CodePage);
  399. if( Node == NULL ) {
  400. //
  401. // we couldn't map a view for the bin containing this cell
  402. //
  403. return FALSE;
  404. }
  405. RtlInitUnicodeString(&Name, L"OEMHAL");
  406. ValueCell = CmpFindValueByName(Hive,
  407. Node,
  408. &Name);
  409. if (ValueCell == HCELL_NIL) {
  410. #ifdef i386
  411. OemHalFont->Buffer = NULL;
  412. OemHalFont->Length = 0;
  413. OemHalFont->MaximumLength = 0;
  414. return TRUE;
  415. #endif
  416. return(FALSE);
  417. }
  418. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  419. if( Value == NULL ) {
  420. //
  421. // we couldn't map a view for the bin containing this cell
  422. //
  423. return FALSE;
  424. }
  425. OemHalFont->Buffer = (PWSTR)CmpValueToData(Hive,Value,&realsize);
  426. if( OemHalFont->Buffer == NULL ) {
  427. //
  428. // HvGetCell inside CmpValueToData failed; bail out safely
  429. //
  430. return FALSE;
  431. }
  432. OemHalFont->Length = (USHORT)realsize;
  433. OemHalFont->MaximumLength = (USHORT)realsize;
  434. return(TRUE);
  435. }
  436. BOOLEAN
  437. CmpFindDrivers(
  438. IN PHHIVE Hive,
  439. IN HCELL_INDEX ControlSet,
  440. IN SERVICE_LOAD_TYPE LoadType,
  441. IN PWSTR BootFileSystem OPTIONAL,
  442. IN PLIST_ENTRY DriverListHead
  443. )
  444. /*++
  445. Routine Description:
  446. Traverses a particular control set and creates a list of boot drivers
  447. to be loaded. This list is unordered, but complete.
  448. Arguments:
  449. Hive - Supplies the hive control structure for the SYSTEM hive.
  450. ControlSet - Supplies the HCELL_INDEX of the root of the control set.
  451. LoadType - Supplies the type of drivers to be loaded (BootLoad,
  452. SystemLoad, AutoLoad, etc)
  453. BootFileSystem - If present, supplies the base name of the boot
  454. filesystem, which is explicitly added to the driver list.
  455. DriverListHead - Supplies a pointer to the head of the (empty) list
  456. of boot drivers to load.
  457. Return Value:
  458. TRUE - List successfully created.
  459. FALSE - Hive is corrupt.
  460. --*/
  461. {
  462. HCELL_INDEX Services;
  463. HCELL_INDEX Control;
  464. HCELL_INDEX GroupOrder;
  465. HCELL_INDEX DriverCell;
  466. UNICODE_STRING Name;
  467. PHCELL_INDEX Index;
  468. int i;
  469. UNICODE_STRING UnicodeString;
  470. UNICODE_STRING BasePath;
  471. WCHAR BaseBuffer[128];
  472. PBOOT_DRIVER_NODE BootFileSystemNode;
  473. PCM_KEY_NODE ControlNode;
  474. PCM_KEY_NODE ServicesNode;
  475. PCM_KEY_NODE Node;
  476. //
  477. // no mapped hives at this point. don't bother releasing cells
  478. //
  479. ASSERT( Hive->ReleaseCellRoutine == NULL );
  480. //
  481. // Find SERVICES node.
  482. //
  483. ControlNode = (PCM_KEY_NODE)HvGetCell(Hive,ControlSet);
  484. if( ControlNode == NULL ) {
  485. //
  486. // we couldn't map a view for the bin containing this cell
  487. //
  488. return FALSE;
  489. }
  490. RtlInitUnicodeString(&Name, L"Services");
  491. Services = CmpFindSubKeyByName(Hive,
  492. ControlNode,
  493. &Name);
  494. if (Services == HCELL_NIL) {
  495. return(FALSE);
  496. }
  497. ServicesNode = (PCM_KEY_NODE)HvGetCell(Hive,Services);
  498. if( ServicesNode == NULL ) {
  499. //
  500. // we couldn't map a view for the bin containing this cell
  501. //
  502. return FALSE;
  503. }
  504. //
  505. // Find CONTROL node.
  506. //
  507. RtlInitUnicodeString(&Name, L"Control");
  508. Control = CmpFindSubKeyByName(Hive,
  509. ControlNode,
  510. &Name);
  511. if (Control == HCELL_NIL) {
  512. return(FALSE);
  513. }
  514. //
  515. // Find GroupOrderList node.
  516. //
  517. RtlInitUnicodeString(&Name, L"GroupOrderList");
  518. Node = (PCM_KEY_NODE)HvGetCell(Hive,Control);
  519. if( Node == NULL ) {
  520. //
  521. // we couldn't map a view for the bin containing this cell
  522. //
  523. return FALSE;
  524. }
  525. GroupOrder = CmpFindSubKeyByName(Hive,
  526. Node,
  527. &Name);
  528. if (GroupOrder == HCELL_NIL) {
  529. return(FALSE);
  530. }
  531. BasePath.Length = 0;
  532. BasePath.MaximumLength = sizeof(BaseBuffer);
  533. BasePath.Buffer = BaseBuffer;
  534. RtlAppendUnicodeToString(&BasePath, L"\\Registry\\Machine\\System\\");
  535. RtlAppendUnicodeToString(&BasePath, L"CurrentControlSet\\Services\\");
  536. i=0;
  537. do {
  538. DriverCell = CmpFindSubKeyByNumber(Hive,ServicesNode,i++);
  539. if (DriverCell != HCELL_NIL) {
  540. if (CmpIsLoadType(Hive, DriverCell, LoadType)) {
  541. CmpAddDriverToList(Hive,
  542. DriverCell,
  543. GroupOrder,
  544. &BasePath,
  545. DriverListHead);
  546. }
  547. }
  548. } while ( DriverCell != HCELL_NIL );
  549. if (ARGUMENT_PRESENT(BootFileSystem)) {
  550. //
  551. // Add boot filesystem to boot driver list
  552. //
  553. RtlInitUnicodeString(&UnicodeString, BootFileSystem);
  554. DriverCell = CmpFindSubKeyByName(Hive,
  555. ServicesNode,
  556. &UnicodeString);
  557. if (DriverCell != HCELL_NIL) {
  558. CmpAddDriverToList(Hive,
  559. DriverCell,
  560. GroupOrder,
  561. &BasePath,
  562. DriverListHead);
  563. //
  564. // mark the Boot Filesystem critical
  565. //
  566. BootFileSystemNode = CONTAINING_RECORD(DriverListHead->Flink,
  567. BOOT_DRIVER_NODE,
  568. ListEntry.Link);
  569. BootFileSystemNode->ErrorControl = SERVICE_ERROR_CRITICAL;
  570. }
  571. }
  572. return(TRUE);
  573. }
  574. BOOLEAN
  575. CmpIsLoadType(
  576. IN PHHIVE Hive,
  577. IN HCELL_INDEX Cell,
  578. IN SERVICE_LOAD_TYPE LoadType
  579. )
  580. /*++
  581. Routine Description:
  582. Determines if the driver is of a specified LoadType, based on its
  583. node values.
  584. Arguments:
  585. Hive - Supplies a pointer to the hive control structure for the system
  586. hive.
  587. Cell - Supplies the cell index of the driver's node in the system hive.
  588. LoadType - Supplies the type of drivers to be loaded (BootLoad,
  589. SystemLoad, AutoLoad, etc)
  590. Return Value:
  591. TRUE - Driver is the correct type and should be loaded.
  592. FALSE - Driver is not the correct type and should not be loaded.
  593. --*/
  594. {
  595. HCELL_INDEX ValueCell;
  596. PLONG Data;
  597. PHCELL_INDEX Index;
  598. UNICODE_STRING Name;
  599. PCM_KEY_VALUE Value;
  600. NTSTATUS Status;
  601. ULONG realsize;
  602. PCM_KEY_NODE Node;
  603. //
  604. // no mapped hives at this point. don't bother releasing cells
  605. //
  606. ASSERT( Hive->ReleaseCellRoutine == NULL );
  607. //
  608. // Must have a Start=BootLoad value in order to be a boot driver, so
  609. // look for that first.
  610. //
  611. Node = (PCM_KEY_NODE)HvGetCell(Hive,Cell);
  612. if( Node == NULL ) {
  613. //
  614. // we couldn't map a view for the bin containing this cell
  615. //
  616. return FALSE;
  617. }
  618. RtlInitUnicodeString(&Name, L"Start");
  619. ValueCell = CmpFindValueByName(Hive,
  620. Node,
  621. &Name);
  622. if (ValueCell == HCELL_NIL) {
  623. return(FALSE);
  624. }
  625. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  626. if( Value == NULL ) {
  627. //
  628. // we couldn't map a view for the bin containing this cell
  629. //
  630. return FALSE;
  631. }
  632. Data = (PLONG)CmpValueToData(Hive,Value,&realsize);
  633. if( Data == NULL ) {
  634. //
  635. // HvGetCell inside CmpValueToData failed; bail out safely
  636. //
  637. return FALSE;
  638. }
  639. if (*Data != LoadType) {
  640. return(FALSE);
  641. }
  642. return(TRUE);
  643. }
  644. BOOLEAN
  645. CmpAddDriverToList(
  646. IN PHHIVE Hive,
  647. IN HCELL_INDEX DriverCell,
  648. IN HCELL_INDEX GroupOrderCell,
  649. IN PUNICODE_STRING RegistryPath,
  650. IN PLIST_ENTRY BootDriverListHead
  651. )
  652. /*++
  653. Routine Description:
  654. This routine allocates a list entry node for a particular driver.
  655. It initializes it with the registry path, filename, group name, and
  656. dependency list. Finally, it inserts the new node into the boot
  657. driver list.
  658. Note that this routine allocates memory by calling the Hive's
  659. memory allocation procedure.
  660. Arguments:
  661. Hive - Supplies a pointer to the hive control structure
  662. DriverCell - Supplies the HCELL_INDEX of the driver's node in the hive.
  663. GroupOrderCell - Supplies the HCELL_INDEX of the GroupOrderList key.
  664. ( \Registry\Machine\System\CurrentControlSet\Control\GroupOrderList )
  665. RegistryPath - Supplies the full registry path to the SERVICES node
  666. of the current control set.
  667. BootDriverListHead - Supplies the head of the boot driver list
  668. Return Value:
  669. TRUE - Driver successfully added to boot driver list.
  670. FALSE - Could not add driver to boot driver list.
  671. --*/
  672. {
  673. PCM_KEY_NODE Driver;
  674. USHORT DriverNameLength;
  675. PCM_KEY_VALUE Value;
  676. PBOOT_DRIVER_NODE DriverNode;
  677. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  678. HCELL_INDEX ValueCell;
  679. HCELL_INDEX Tag;
  680. UNICODE_STRING UnicodeString;
  681. PUNICODE_STRING FileName;
  682. NTSTATUS Status;
  683. ULONG Length;
  684. PHCELL_INDEX Index;
  685. ULONG realsize;
  686. PULONG TempULong;
  687. PWSTR TempBuffer;
  688. //
  689. // no mapped hives at this point. don't bother releasing cells
  690. //
  691. ASSERT( Hive->ReleaseCellRoutine == NULL );
  692. Driver = (PCM_KEY_NODE)HvGetCell(Hive, DriverCell);
  693. if( Driver == NULL ) {
  694. //
  695. // we couldn't map a view for the bin containing this cell
  696. //
  697. return FALSE;
  698. }
  699. DriverNode = (Hive->Allocate)(sizeof(BOOT_DRIVER_NODE),FALSE,CM_FIND_LEAK_TAG1);
  700. if (DriverNode == NULL) {
  701. return(FALSE);
  702. }
  703. DriverEntry = &DriverNode->ListEntry;
  704. DriverEntry->RegistryPath.Buffer = NULL;
  705. DriverEntry->FilePath.Buffer = NULL;
  706. if (Driver->Flags & KEY_COMP_NAME) {
  707. DriverNode->Name.Length = CmpCompressedNameSize(Driver->Name,Driver->NameLength);
  708. DriverNode->Name.Buffer = (Hive->Allocate)(DriverNode->Name.Length, FALSE,CM_FIND_LEAK_TAG2);
  709. if (DriverNode->Name.Buffer == NULL) {
  710. return(FALSE);
  711. }
  712. CmpCopyCompressedName(DriverNode->Name.Buffer,
  713. DriverNode->Name.Length,
  714. Driver->Name,
  715. Driver->NameLength);
  716. } else {
  717. DriverNode->Name.Length = Driver->NameLength;
  718. DriverNode->Name.Buffer = (Hive->Allocate)(DriverNode->Name.Length, FALSE,CM_FIND_LEAK_TAG2);
  719. if (DriverNode->Name.Buffer == NULL) {
  720. return(FALSE);
  721. }
  722. RtlCopyMemory((PVOID)(DriverNode->Name.Buffer), (PVOID)(Driver->Name), Driver->NameLength);
  723. }
  724. DriverNode->Name.MaximumLength = DriverNode->Name.Length;
  725. DriverNameLength = DriverNode->Name.Length;
  726. //
  727. // Check for ImagePath value, which will override the default name
  728. // if it is present.
  729. //
  730. RtlInitUnicodeString(&UnicodeString, L"ImagePath");
  731. ValueCell = CmpFindValueByName(Hive,
  732. Driver,
  733. &UnicodeString);
  734. if (ValueCell == HCELL_NIL) {
  735. //
  736. // No ImagePath, so generate default filename.
  737. // Build up Unicode filename ("system32\drivers\<nodename>.sys");
  738. //
  739. Length = sizeof(L"System32\\Drivers\\") +
  740. DriverNameLength +
  741. sizeof(L".sys");
  742. FileName = &DriverEntry->FilePath;
  743. FileName->Length = 0;
  744. FileName->MaximumLength = (USHORT)Length;
  745. FileName->Buffer = (PWSTR)(Hive->Allocate)(Length, FALSE,CM_FIND_LEAK_TAG3);
  746. if (FileName->Buffer == NULL) {
  747. return(FALSE);
  748. }
  749. if (!NT_SUCCESS(RtlAppendUnicodeToString(FileName, L"System32\\"))) {
  750. return(FALSE);
  751. }
  752. if (!NT_SUCCESS(RtlAppendUnicodeToString(FileName, L"Drivers\\"))) {
  753. return(FALSE);
  754. }
  755. if (!NT_SUCCESS(
  756. RtlAppendUnicodeStringToString(FileName,
  757. &DriverNode->Name))) {
  758. return(FALSE);
  759. }
  760. if (!NT_SUCCESS(RtlAppendUnicodeToString(FileName, L".sys"))) {
  761. return(FALSE);
  762. }
  763. } else {
  764. Value = (PCM_KEY_VALUE)HvGetCell(Hive,ValueCell);
  765. if( Value == NULL ) {
  766. //
  767. // we couldn't map a view for the bin containing this cell
  768. //
  769. return FALSE;
  770. }
  771. FileName = &DriverEntry->FilePath;
  772. TempBuffer = (PWSTR)CmpValueToData(Hive,Value,&realsize);
  773. FileName->Buffer = (PWSTR)(Hive->Allocate)(realsize, FALSE,CM_FIND_LEAK_TAG3);
  774. if( (FileName->Buffer == NULL) || (TempBuffer == NULL) ) {
  775. //
  776. // HvGetCell inside CmpValueToData failed; bail out safely
  777. //
  778. return FALSE;
  779. }
  780. RtlCopyMemory((PVOID)(FileName->Buffer), (PVOID)(TempBuffer), realsize);
  781. FileName->MaximumLength = FileName->Length = (USHORT)realsize;
  782. }
  783. FileName = &DriverEntry->RegistryPath;
  784. FileName->Length = 0;
  785. FileName->MaximumLength = RegistryPath->Length + DriverNameLength;
  786. FileName->Buffer = (Hive->Allocate)(FileName->MaximumLength,FALSE,CM_FIND_LEAK_TAG4);
  787. if (FileName->Buffer == NULL) {
  788. return(FALSE);
  789. }
  790. RtlAppendUnicodeStringToString(FileName, RegistryPath);
  791. RtlAppendUnicodeStringToString(FileName, &DriverNode->Name);
  792. InsertHeadList(BootDriverListHead, &DriverEntry->Link);
  793. //
  794. // Find "ErrorControl" value
  795. //
  796. RtlInitUnicodeString(&UnicodeString, L"ErrorControl");
  797. ValueCell = CmpFindValueByName(Hive,
  798. Driver,
  799. &UnicodeString);
  800. if (ValueCell == HCELL_NIL) {
  801. DriverNode->ErrorControl = NormalError;
  802. } else {
  803. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  804. if( Value == NULL ) {
  805. //
  806. // we couldn't map a view for the bin containing this cell
  807. //
  808. return FALSE;
  809. }
  810. TempULong = (PULONG)CmpValueToData(Hive,Value,&realsize);
  811. if( TempULong == NULL ) {
  812. //
  813. // HvGetCell inside CmpValueToData failed; bail out safely
  814. //
  815. return FALSE;
  816. }
  817. DriverNode->ErrorControl = *TempULong;
  818. }
  819. //
  820. // Find "Group" value
  821. //
  822. RtlInitUnicodeString(&UnicodeString, L"group");
  823. ValueCell = CmpFindValueByName(Hive,
  824. Driver,
  825. &UnicodeString);
  826. if (ValueCell == HCELL_NIL) {
  827. DriverNode->Group.Length = 0;
  828. DriverNode->Group.MaximumLength = 0;
  829. DriverNode->Group.Buffer = NULL;
  830. } else {
  831. Value = (PCM_KEY_VALUE)HvGetCell(Hive, ValueCell);
  832. if( Value == NULL ) {
  833. //
  834. // we couldn't map a view for the bin containing this cell
  835. //
  836. return FALSE;
  837. }
  838. DriverNode->Group.Buffer = (PWSTR)CmpValueToData(Hive,Value,&realsize);
  839. if( DriverNode->Group.Buffer == NULL ) {
  840. //
  841. // HvGetCell inside CmpValueToData failed; bail out safely
  842. //
  843. return FALSE;
  844. }
  845. DriverNode->Group.Length = (USHORT)realsize - sizeof(WCHAR);
  846. DriverNode->Group.MaximumLength = (USHORT)DriverNode->Group.Length;
  847. }
  848. //
  849. // Calculate the tag value for the driver. If the driver has no tag,
  850. // this defaults to 0xffffffff, so the driver is loaded last in the
  851. // group.
  852. //
  853. RtlInitUnicodeString(&UnicodeString, L"Tag");
  854. Tag = CmpFindValueByName(Hive,
  855. Driver,
  856. &UnicodeString);
  857. if (Tag == HCELL_NIL) {
  858. DriverNode->Tag = LOAD_LAST;
  859. } else {
  860. //
  861. // Now we have to find this tag in the tag list for the group.
  862. // If the tag is not in the tag list, then it defaults to 0xfffffffe,
  863. // so it is loaded after all the drivers in the tag list, but before
  864. // all the drivers without tags at all.
  865. //
  866. DriverNode->Tag = CmpFindTagIndex(Hive,
  867. Tag,
  868. GroupOrderCell,
  869. &DriverNode->Group);
  870. }
  871. return(TRUE);
  872. }
  873. BOOLEAN
  874. CmpSortDriverList(
  875. IN PHHIVE Hive,
  876. IN HCELL_INDEX ControlSet,
  877. IN PLIST_ENTRY DriverListHead
  878. )
  879. /*++
  880. Routine Description:
  881. Sorts the list of boot drivers by their groups based on the group
  882. ordering in <control_set>\CONTROL\SERVICE_GROUP_ORDER:list
  883. Does NOT do dependency ordering.
  884. Arguments:
  885. Hive - Supplies the hive control structure for the SYSTEM hive.
  886. ControlSet - Supplies the HCELL_INDEX of the root of the control set.
  887. DriverListHead - Supplies a pointer to the head of the list of
  888. boot drivers to be sorted.
  889. Return Value:
  890. TRUE - List successfully sorted
  891. FALSE - List is inconsistent and could not be sorted.
  892. --*/
  893. {
  894. HCELL_INDEX Controls;
  895. HCELL_INDEX GroupOrder;
  896. HCELL_INDEX ListCell;
  897. UNICODE_STRING Name;
  898. UNICODE_STRING DependList;
  899. PHCELL_INDEX Index;
  900. NTSTATUS Status;
  901. PCM_KEY_VALUE ListNode;
  902. ULONG realsize;
  903. PCM_KEY_NODE Node;
  904. //
  905. // no mapped hives at this point. don't bother releasing cells
  906. //
  907. ASSERT( Hive->ReleaseCellRoutine == NULL );
  908. //
  909. // Find "CONTROL" node.
  910. //
  911. Node = (PCM_KEY_NODE)HvGetCell(Hive,ControlSet);
  912. if( Node == NULL ) {
  913. //
  914. // we couldn't map a view for the bin containing this cell
  915. //
  916. return FALSE;
  917. }
  918. RtlInitUnicodeString(&Name, L"Control");
  919. Controls = CmpFindSubKeyByName(Hive,
  920. Node,
  921. &Name);
  922. if (Controls == HCELL_NIL) {
  923. return(FALSE);
  924. }
  925. //
  926. // Find "SERVICE_GROUP_ORDER" subkey
  927. //
  928. Node = (PCM_KEY_NODE)HvGetCell(Hive,Controls);
  929. if( Node == NULL ) {
  930. //
  931. // we couldn't map a view for the bin containing this cell
  932. //
  933. return FALSE;
  934. }
  935. RtlInitUnicodeString(&Name, L"ServiceGroupOrder");
  936. GroupOrder = CmpFindSubKeyByName(Hive,
  937. Node,
  938. &Name);
  939. if (GroupOrder == HCELL_NIL) {
  940. return(FALSE);
  941. }
  942. //
  943. // Find "list" value
  944. //
  945. Node = (PCM_KEY_NODE)HvGetCell(Hive,GroupOrder);
  946. if( Node == NULL ) {
  947. //
  948. // we couldn't map a view for the bin containing this cell
  949. //
  950. return FALSE;
  951. }
  952. RtlInitUnicodeString(&Name, L"list");
  953. ListCell = CmpFindValueByName(Hive,
  954. Node,
  955. &Name);
  956. if (ListCell == HCELL_NIL) {
  957. return(FALSE);
  958. }
  959. ListNode = (PCM_KEY_VALUE)HvGetCell(Hive, ListCell);
  960. if( ListNode == NULL ) {
  961. //
  962. // we couldn't map a view for the bin containing this cell
  963. //
  964. return FALSE;
  965. }
  966. if (ListNode->Type != REG_MULTI_SZ) {
  967. return(FALSE);
  968. }
  969. DependList.Buffer = (PWSTR)CmpValueToData(Hive,ListNode,&realsize);
  970. if( DependList.Buffer == NULL ) {
  971. //
  972. // HvGetCell inside CmpValueToData failed; bail out safely
  973. //
  974. return FALSE;
  975. }
  976. DependList.Length = DependList.MaximumLength = (USHORT)realsize - sizeof(WCHAR);
  977. //
  978. // Dependency list is now pointed to by DependList->Buffer. We need
  979. // to sort the driver entry list.
  980. //
  981. return (CmpDoSort(DriverListHead, &DependList));
  982. }
  983. BOOLEAN
  984. CmpDoSort(
  985. IN PLIST_ENTRY DriverListHead,
  986. IN PUNICODE_STRING OrderList
  987. )
  988. /*++
  989. Routine Description:
  990. Sorts the boot driver list based on the order list
  991. Start with the last entry in the group order list and work towards
  992. the beginning. For each group entry, move all driver entries that
  993. are members of the group to the front of the list. Driver entries
  994. with no groups, or with a group that does not match any in the
  995. group list will be shoved to the end of the list.
  996. Arguments:
  997. DriverListHead - Supplies a pointer to the head of the list of
  998. boot drivers to be sorted.
  999. OrderList - Supplies pointer to the order list
  1000. Return Value:
  1001. TRUE - List successfully ordered
  1002. FALSE - List is inconsistent and could not be ordered.
  1003. --*/
  1004. {
  1005. PWSTR Current;
  1006. PWSTR End;
  1007. PLIST_ENTRY Next;
  1008. PBOOT_DRIVER_NODE CurrentNode;
  1009. UNICODE_STRING CurrentGroup;
  1010. Current = (PWSTR) ((PUCHAR)(OrderList->Buffer)+OrderList->Length);
  1011. while (Current > OrderList->Buffer) {
  1012. do {
  1013. if (*(Current) == UNICODE_NULL) {
  1014. End = Current;
  1015. }
  1016. --Current;
  1017. } while ((*(Current-1) != UNICODE_NULL) &&
  1018. ( Current != OrderList->Buffer));
  1019. //
  1020. // Current now points to the beginning of the NULL-terminated
  1021. // Unicode string.
  1022. // End now points to the end of the string
  1023. //
  1024. CurrentGroup.Length = (USHORT) ((PCHAR)End - (PCHAR)Current);
  1025. CurrentGroup.MaximumLength = CurrentGroup.Length;
  1026. CurrentGroup.Buffer = Current;
  1027. Next = DriverListHead->Flink;
  1028. while (Next != DriverListHead) {
  1029. CurrentNode = CONTAINING_RECORD(Next,
  1030. BOOT_DRIVER_NODE,
  1031. ListEntry.Link);
  1032. Next = CurrentNode->ListEntry.Link.Flink;
  1033. if (CurrentNode->Group.Buffer != NULL) {
  1034. if (RtlEqualUnicodeString(&CurrentGroup, &CurrentNode->Group,TRUE)) {
  1035. RemoveEntryList(&CurrentNode->ListEntry.Link);
  1036. InsertHeadList(DriverListHead,
  1037. &CurrentNode->ListEntry.Link);
  1038. }
  1039. }
  1040. }
  1041. --Current;
  1042. }
  1043. return(TRUE);
  1044. }
  1045. BOOLEAN
  1046. CmpResolveDriverDependencies(
  1047. IN PLIST_ENTRY DriverListHead
  1048. )
  1049. /*++
  1050. Routine Description:
  1051. This routine orders driver nodes in a group based on their dependencies
  1052. on one another. It removes any drivers that have circular dependencies
  1053. from the list.
  1054. Arguments:
  1055. DriverListHead - Supplies a pointer to the head of the list of
  1056. boot drivers to be sorted.
  1057. Return Value:
  1058. TRUE - Dependencies successfully resolved
  1059. FALSE - Corrupt hive.
  1060. --*/
  1061. {
  1062. PLIST_ENTRY CurrentEntry;
  1063. PBOOT_DRIVER_NODE GroupStart;
  1064. PBOOT_DRIVER_NODE GroupEnd;
  1065. PBOOT_DRIVER_NODE CurrentNode;
  1066. CurrentEntry = DriverListHead->Flink;
  1067. while (CurrentEntry != DriverListHead) {
  1068. //
  1069. // The list is already ordered by groups. Find the first and
  1070. // last entry in each group, and order each of these sub-lists
  1071. // based on their dependencies.
  1072. //
  1073. GroupStart = CONTAINING_RECORD(CurrentEntry,
  1074. BOOT_DRIVER_NODE,
  1075. ListEntry.Link);
  1076. do {
  1077. GroupEnd = CONTAINING_RECORD(CurrentEntry,
  1078. BOOT_DRIVER_NODE,
  1079. ListEntry.Link);
  1080. CurrentEntry = CurrentEntry->Flink;
  1081. CurrentNode = CONTAINING_RECORD(CurrentEntry,
  1082. BOOT_DRIVER_NODE,
  1083. ListEntry.Link);
  1084. if (CurrentEntry == DriverListHead) {
  1085. break;
  1086. }
  1087. if (!RtlEqualUnicodeString(&GroupStart->Group,
  1088. &CurrentNode->Group,
  1089. TRUE)) {
  1090. break;
  1091. }
  1092. } while ( CurrentEntry != DriverListHead );
  1093. //
  1094. // GroupStart now points to the first driver node in the group,
  1095. // and GroupEnd points to the last driver node in the group.
  1096. //
  1097. CmpOrderGroup(GroupStart, GroupEnd);
  1098. }
  1099. return(TRUE);
  1100. }
  1101. BOOLEAN
  1102. CmpOrderGroup(
  1103. IN PBOOT_DRIVER_NODE GroupStart,
  1104. IN PBOOT_DRIVER_NODE GroupEnd
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. Reorders the nodes in a driver group based on their tag values.
  1109. Arguments:
  1110. GroupStart - Supplies the first node in the group.
  1111. GroupEnd - Supplies the last node in the group.
  1112. Return Value:
  1113. TRUE - Group successfully reordered
  1114. FALSE - Circular dependencies detected.
  1115. --*/
  1116. {
  1117. PBOOT_DRIVER_NODE Current;
  1118. PBOOT_DRIVER_NODE Previous;
  1119. PLIST_ENTRY ListEntry;
  1120. BOOLEAN StartOver=FALSE;
  1121. if (GroupStart == GroupEnd) {
  1122. return(TRUE);
  1123. }
  1124. Current = GroupStart;
  1125. do {
  1126. //
  1127. // If the driver before the current one has a lower tag, then
  1128. // we do not need to move it. If not, then remove the driver
  1129. // from the list and scan backwards until we find a driver with
  1130. // a tag that is <= the current tag, or we reach the beginning
  1131. // of the list.
  1132. //
  1133. Previous = Current;
  1134. ListEntry = Current->ListEntry.Link.Flink;
  1135. Current = CONTAINING_RECORD(ListEntry,
  1136. BOOT_DRIVER_NODE,
  1137. ListEntry.Link);
  1138. if (Previous->Tag > Current->Tag) {
  1139. //
  1140. // Remove the Current driver from the list, and search
  1141. // backwards until we find a tag that is <= the current
  1142. // driver's tag. Reinsert the current driver there.
  1143. //
  1144. if (Current == GroupEnd) {
  1145. ListEntry = Current->ListEntry.Link.Blink;
  1146. GroupEnd = CONTAINING_RECORD(ListEntry,
  1147. BOOT_DRIVER_NODE,
  1148. ListEntry.Link);
  1149. }
  1150. RemoveEntryList(&Current->ListEntry.Link);
  1151. while ( (Previous->Tag > Current->Tag) &&
  1152. (Previous != GroupStart) ) {
  1153. ListEntry = Previous->ListEntry.Link.Blink;
  1154. Previous = CONTAINING_RECORD(ListEntry,
  1155. BOOT_DRIVER_NODE,
  1156. ListEntry.Link);
  1157. }
  1158. InsertTailList(&Previous->ListEntry.Link,
  1159. &Current->ListEntry.Link);
  1160. if (Previous == GroupStart) {
  1161. GroupStart = Current;
  1162. }
  1163. }
  1164. } while ( Current != GroupEnd );
  1165. return(TRUE);
  1166. }
  1167. BOOLEAN
  1168. CmpValidateSelect(
  1169. IN PHHIVE SystemHive,
  1170. IN HCELL_INDEX RootCell
  1171. )
  1172. /*++
  1173. Routine Description:
  1174. This routines parses the SYSTEM hive and "Select" node
  1175. and verifies the following values:
  1176. Current
  1177. Default
  1178. Failed
  1179. LastKnownGood
  1180. If any of these is missing the the loader will put the corrupt
  1181. system hive message
  1182. This routine is to be called by the loader just after it loads the
  1183. system hive. It's purpose is to ensure a uniform and consistent way
  1184. to treat missing values in this area.
  1185. Arguments:
  1186. SystemHive - Supplies the hive control structure for the SYSTEM hive.
  1187. RootCell - Supplies the HCELL_INDEX of the root cell of the hive.
  1188. Return Value:
  1189. TRUE - all the values are here
  1190. FALSE - some of them are missing
  1191. --*/
  1192. {
  1193. HCELL_INDEX Select;
  1194. PCM_KEY_NODE Node;
  1195. UNICODE_STRING Name;
  1196. //
  1197. // no mapped hives at this point. don't bother releasing cells
  1198. //
  1199. ASSERT( SystemHive->ReleaseCellRoutine == NULL );
  1200. //
  1201. // Find \SYSTEM\SELECT node.
  1202. //
  1203. Node = (PCM_KEY_NODE)HvGetCell(SystemHive,RootCell);
  1204. if( Node == NULL ) {
  1205. //
  1206. // we couldn't map a view for the bin containing this cell
  1207. //
  1208. return FALSE;
  1209. }
  1210. RtlInitUnicodeString(&Name, L"select");
  1211. Select = CmpFindSubKeyByName(SystemHive,
  1212. Node,
  1213. &Name);
  1214. if (Select == HCELL_NIL) {
  1215. return FALSE;
  1216. }
  1217. //
  1218. // Find AutoSelect value
  1219. //
  1220. Node = (PCM_KEY_NODE)HvGetCell(SystemHive,Select);
  1221. if( Node == NULL ) {
  1222. //
  1223. // we couldn't map a view for the bin containing this cell
  1224. //
  1225. return FALSE;
  1226. }
  1227. // search for current
  1228. RtlInitUnicodeString(&Name, L"current");
  1229. Select = CmpFindValueByName(SystemHive,
  1230. Node,
  1231. &Name);
  1232. if (Select == HCELL_NIL) {
  1233. return FALSE;
  1234. }
  1235. // search for default
  1236. RtlInitUnicodeString(&Name, L"default");
  1237. Select = CmpFindValueByName(SystemHive,
  1238. Node,
  1239. &Name);
  1240. if (Select == HCELL_NIL) {
  1241. return FALSE;
  1242. }
  1243. // search for failed
  1244. RtlInitUnicodeString(&Name, L"failed");
  1245. Select = CmpFindValueByName(SystemHive,
  1246. Node,
  1247. &Name);
  1248. if (Select == HCELL_NIL) {
  1249. return FALSE;
  1250. }
  1251. // search for LKG
  1252. RtlInitUnicodeString(&Name, L"LastKnownGood");
  1253. Select = CmpFindValueByName(SystemHive,
  1254. Node,
  1255. &Name);
  1256. if (Select == HCELL_NIL) {
  1257. return FALSE;
  1258. }
  1259. return TRUE;
  1260. }
  1261. HCELL_INDEX
  1262. CmpFindControlSet(
  1263. IN PHHIVE SystemHive,
  1264. IN HCELL_INDEX RootCell,
  1265. IN PUNICODE_STRING SelectName,
  1266. OUT PBOOLEAN AutoSelect
  1267. )
  1268. /*++
  1269. Routine Description:
  1270. This routines parses the SYSTEM hive and "Select" node
  1271. to locate the control set to be used for booting.
  1272. Note that this routines also updates the value of Current to reflect
  1273. the control set that was just found. This is what we want to do
  1274. when this is called during boot. During I/O initialization, this
  1275. is irrelevant, since we're just changing it to what it already is.
  1276. Arguments:
  1277. SystemHive - Supplies the hive control structure for the SYSTEM hive.
  1278. RootCell - Supplies the HCELL_INDEX of the root cell of the hive.
  1279. SelectName - Supplies the name of the Select value to be used in
  1280. determining the control set. This should be one of "Current"
  1281. "Default" or "LastKnownGood"
  1282. AutoSelect - Returns the value of the AutoSelect value under
  1283. the Select node.
  1284. Return Value:
  1285. != HCELL_NIL - Cell Index of the control set to be used for booting.
  1286. == HCELL_NIL - Indicates the hive is corrupt or inconsistent
  1287. --*/
  1288. {
  1289. HCELL_INDEX Select;
  1290. HCELL_INDEX ValueCell;
  1291. HCELL_INDEX ControlSet;
  1292. HCELL_INDEX AutoSelectCell;
  1293. NTSTATUS Status;
  1294. UNICODE_STRING Name;
  1295. ANSI_STRING AnsiString;
  1296. PHCELL_INDEX Index;
  1297. PCM_KEY_VALUE Value;
  1298. PULONG ControlSetIndex;
  1299. PULONG CurrentControl;
  1300. CHAR AsciiBuffer[128];
  1301. WCHAR UnicodeBuffer[128];
  1302. ULONG realsize;
  1303. PCM_KEY_NODE Node;
  1304. PBOOLEAN TempBoolean;
  1305. //
  1306. // no mapped hives at this point. don't bother releasing cells
  1307. //
  1308. ASSERT( SystemHive->ReleaseCellRoutine == NULL );
  1309. //
  1310. // Find \SYSTEM\SELECT node.
  1311. //
  1312. Node = (PCM_KEY_NODE)HvGetCell(SystemHive,RootCell);
  1313. if( Node == NULL ) {
  1314. //
  1315. // we couldn't map a view for the bin containing this cell
  1316. //
  1317. return HCELL_NIL;
  1318. }
  1319. RtlInitUnicodeString(&Name, L"select");
  1320. Select = CmpFindSubKeyByName(SystemHive,
  1321. Node,
  1322. &Name);
  1323. if (Select == HCELL_NIL) {
  1324. return(HCELL_NIL);
  1325. }
  1326. //
  1327. // Find AutoSelect value
  1328. //
  1329. Node = (PCM_KEY_NODE)HvGetCell(SystemHive,Select);
  1330. if( Node == NULL ) {
  1331. //
  1332. // we couldn't map a view for the bin containing this cell
  1333. //
  1334. return HCELL_NIL;
  1335. }
  1336. RtlInitUnicodeString(&Name, L"AutoSelect");
  1337. AutoSelectCell = CmpFindValueByName(SystemHive,
  1338. Node,
  1339. &Name);
  1340. if (AutoSelectCell == HCELL_NIL) {
  1341. //
  1342. // It's not there, we don't care. Set autoselect to TRUE
  1343. //
  1344. *AutoSelect = TRUE;
  1345. } else {
  1346. Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
  1347. if( Value == NULL ) {
  1348. //
  1349. // we couldn't map a view for the bin containing this cell
  1350. //
  1351. return HCELL_NIL;
  1352. }
  1353. TempBoolean = (PBOOLEAN)(CmpValueToData(SystemHive,Value,&realsize));
  1354. if( TempBoolean == NULL ) {
  1355. //
  1356. // HvGetCell inside CmpValueToData failed; bail out safely
  1357. //
  1358. return HCELL_NIL;
  1359. }
  1360. *AutoSelect = *TempBoolean;
  1361. }
  1362. Node = (PCM_KEY_NODE)HvGetCell(SystemHive,Select);
  1363. if( Node == NULL ) {
  1364. //
  1365. // we couldn't map a view for the bin containing this cell
  1366. //
  1367. return HCELL_NIL;
  1368. }
  1369. ValueCell = CmpFindValueByName(SystemHive,
  1370. Node,
  1371. SelectName);
  1372. if (ValueCell == HCELL_NIL) {
  1373. return(HCELL_NIL);
  1374. }
  1375. Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  1376. if( Value == NULL ) {
  1377. //
  1378. // we couldn't map a view for the bin containing this cell
  1379. //
  1380. return HCELL_NIL;
  1381. }
  1382. if (Value->Type != REG_DWORD) {
  1383. return(HCELL_NIL);
  1384. }
  1385. ControlSetIndex = (PULONG)CmpValueToData(SystemHive, Value,&realsize);
  1386. if( ControlSetIndex == NULL ) {
  1387. //
  1388. // HvGetCell inside CmpValueToData failed; bail out safely
  1389. //
  1390. return HCELL_NIL;
  1391. }
  1392. //
  1393. // Find appropriate control set
  1394. //
  1395. sprintf(AsciiBuffer, "ControlSet%03d", *ControlSetIndex);
  1396. AnsiString.Length = AnsiString.MaximumLength = (USHORT) strlen(&(AsciiBuffer[0]));
  1397. AnsiString.Buffer = AsciiBuffer;
  1398. Name.MaximumLength = 128*sizeof(WCHAR);
  1399. Name.Buffer = UnicodeBuffer;
  1400. Status = RtlAnsiStringToUnicodeString(&Name,
  1401. &AnsiString,
  1402. FALSE);
  1403. if (!NT_SUCCESS(Status)) {
  1404. return(HCELL_NIL);
  1405. }
  1406. Node = (PCM_KEY_NODE)HvGetCell(SystemHive,RootCell);
  1407. if( Node == NULL ) {
  1408. //
  1409. // we couldn't map a view for the bin containing this cell
  1410. //
  1411. return HCELL_NIL;
  1412. }
  1413. ControlSet = CmpFindSubKeyByName(SystemHive,
  1414. Node,
  1415. &Name);
  1416. if (ControlSet == HCELL_NIL) {
  1417. return(HCELL_NIL);
  1418. }
  1419. //
  1420. // Control set was successfully found, so update the value in "Current"
  1421. // to reflect the control set we are going to use.
  1422. //
  1423. Node = (PCM_KEY_NODE)HvGetCell(SystemHive,Select);
  1424. if( Node == NULL ) {
  1425. //
  1426. // we couldn't map a view for the bin containing this cell
  1427. //
  1428. return HCELL_NIL;
  1429. }
  1430. RtlInitUnicodeString(&Name, L"Current");
  1431. ValueCell = CmpFindValueByName(SystemHive,
  1432. Node,
  1433. &Name);
  1434. if (ValueCell != HCELL_NIL) {
  1435. Value = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  1436. if( Value == NULL ) {
  1437. //
  1438. // we couldn't map a view for the bin containing this cell
  1439. //
  1440. return HCELL_NIL;
  1441. }
  1442. if (Value->Type == REG_DWORD) {
  1443. CurrentControl = (PULONG)CmpValueToData(SystemHive, Value,&realsize);
  1444. if( CurrentControl == NULL ) {
  1445. //
  1446. // HvGetCell inside CmpValueToData failed; bail out safely
  1447. //
  1448. return HCELL_NIL;
  1449. }
  1450. *CurrentControl = *ControlSetIndex;
  1451. }
  1452. }
  1453. return(ControlSet);
  1454. }
  1455. VOID
  1456. CmpSetCurrentProfile(
  1457. IN PHHIVE Hive,
  1458. IN HCELL_INDEX ControlSet,
  1459. IN PCM_HARDWARE_PROFILE Profile
  1460. )
  1461. /*++
  1462. Routine Description:
  1463. Edits the in-memory copy of the registry to reflect the hardware
  1464. profile that the system is booting from.
  1465. Arguments:
  1466. Hive - Supplies a pointer to the hive control structure
  1467. ControlSet - Supplies the HCELL_INDEX of the current control set.
  1468. Profile - Supplies a pointer to the selected hardware profile
  1469. Return Value:
  1470. None.
  1471. --*/
  1472. {
  1473. HCELL_INDEX IDConfigDB;
  1474. PCM_KEY_NODE IDConfigNode;
  1475. HCELL_INDEX CurrentConfigCell;
  1476. PCM_KEY_VALUE CurrentConfigValue;
  1477. UNICODE_STRING Name;
  1478. PULONG CurrentConfig;
  1479. ULONG realsize;
  1480. //
  1481. // no mapped hives at this point. don't bother releasing cells
  1482. //
  1483. ASSERT( Hive->ReleaseCellRoutine == NULL );
  1484. IDConfigDB = CmpFindProfileOption(Hive,
  1485. ControlSet,
  1486. NULL,
  1487. NULL,
  1488. NULL);
  1489. if (IDConfigDB != HCELL_NIL) {
  1490. IDConfigNode = (PCM_KEY_NODE)HvGetCell(Hive, IDConfigDB);
  1491. if( IDConfigNode == NULL ) {
  1492. //
  1493. // we couldn't map a view for the bin containing this cell
  1494. //
  1495. return;
  1496. }
  1497. RtlInitUnicodeString(&Name, L"CurrentConfig");
  1498. CurrentConfigCell = CmpFindValueByName(Hive,
  1499. IDConfigNode,
  1500. &Name);
  1501. if (CurrentConfigCell != HCELL_NIL) {
  1502. CurrentConfigValue = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentConfigCell);
  1503. if( CurrentConfigValue == NULL ) {
  1504. //
  1505. // we couldn't map a view for the bin containing this cell
  1506. //
  1507. return;
  1508. }
  1509. if (CurrentConfigValue->Type == REG_DWORD) {
  1510. CurrentConfig = (PULONG)CmpValueToData(Hive,
  1511. CurrentConfigValue,
  1512. &realsize);
  1513. if( CurrentConfig == NULL ) {
  1514. //
  1515. // HvGetCell inside CmpValueToData failed; bail out safely
  1516. //
  1517. return;
  1518. }
  1519. *CurrentConfig = Profile->Id;
  1520. }
  1521. }
  1522. }
  1523. }
  1524. HCELL_INDEX
  1525. CmpFindProfileOption(
  1526. IN PHHIVE SystemHive,
  1527. IN HCELL_INDEX ControlSet,
  1528. OUT OPTIONAL PCM_HARDWARE_PROFILE_LIST *ReturnedProfileList,
  1529. OUT OPTIONAL PCM_HARDWARE_PROFILE_ALIAS_LIST *ReturnedAliasList,
  1530. OUT OPTIONAL PULONG ProfileTimeout
  1531. )
  1532. /*++
  1533. Routine Description:
  1534. This routines parses the SYSTEM hive and locates the
  1535. "CurrentControlSet\Control\IDConfigDB" node to determine the
  1536. hardware profile configuration settings.
  1537. Arguments:
  1538. SystemHive - Supplies the hive control structure for the SYSTEM hive.
  1539. ControlSet - Supplies the HCELL_INDEX of the root cell of the hive.
  1540. ProfileList - Returns the list of available hardware profiles sorted
  1541. by preference. Will be allocated by this routine if
  1542. NULL is passed in, or a pointer to a CM_HARDWARE_PROFILE_LIST
  1543. structure that is too small is passed in.
  1544. ProfileTimeout - Returns the timeout value for the config menu.
  1545. Return Value:
  1546. != HCELL_NIL - Cell Index of the IDConfigDB node.
  1547. == HCELL_NIL - Indicates IDConfigDB does not exist
  1548. --*/
  1549. {
  1550. HCELL_INDEX ControlCell;
  1551. HCELL_INDEX IDConfigDB;
  1552. HCELL_INDEX DefaultCell;
  1553. HCELL_INDEX TimeoutCell;
  1554. HCELL_INDEX ProfileCell;
  1555. HCELL_INDEX AliasCell;
  1556. HCELL_INDEX HWCell;
  1557. PCM_KEY_NODE HWNode;
  1558. PCM_KEY_NODE ProfileNode;
  1559. PCM_KEY_NODE AliasNode;
  1560. PCM_KEY_NODE ConfigDBNode;
  1561. PCM_KEY_NODE Control;
  1562. PCM_KEY_VALUE TimeoutValue;
  1563. UNICODE_STRING Name;
  1564. ULONG realsize;
  1565. PCM_HARDWARE_PROFILE_LIST ProfileList;
  1566. PCM_HARDWARE_PROFILE_ALIAS_LIST AliasList;
  1567. ULONG ProfileCount;
  1568. ULONG AliasCount;
  1569. ULONG i,j;
  1570. WCHAR NameBuf[20];
  1571. PCM_KEY_NODE Node;
  1572. PULONG TempULong;
  1573. //
  1574. // no mapped hives at this point. don't bother releasing cells
  1575. //
  1576. ASSERT( SystemHive->ReleaseCellRoutine == NULL );
  1577. //
  1578. // Find Control node
  1579. //
  1580. Node = (PCM_KEY_NODE)HvGetCell(SystemHive,ControlSet);
  1581. if( Node == NULL ) {
  1582. //
  1583. // we couldn't map a view for the bin containing this cell
  1584. //
  1585. return HCELL_NIL;
  1586. }
  1587. RtlInitUnicodeString(&Name, L"Control");
  1588. ControlCell = CmpFindSubKeyByName(SystemHive,
  1589. Node,
  1590. &Name);
  1591. if (ControlCell == HCELL_NIL) {
  1592. return(HCELL_NIL);
  1593. }
  1594. Control = (PCM_KEY_NODE)HvGetCell(SystemHive, ControlCell);
  1595. if( Control == NULL ) {
  1596. //
  1597. // we couldn't map a view for the bin containing this cell
  1598. //
  1599. return HCELL_NIL;
  1600. }
  1601. //
  1602. // Find IDConfigDB node
  1603. //
  1604. RtlInitUnicodeString(&Name, L"IDConfigDB");
  1605. IDConfigDB = CmpFindSubKeyByName(SystemHive,
  1606. Control,
  1607. &Name);
  1608. if (IDConfigDB == HCELL_NIL) {
  1609. return(HCELL_NIL);
  1610. }
  1611. ConfigDBNode = (PCM_KEY_NODE)HvGetCell(SystemHive, IDConfigDB);
  1612. if( ConfigDBNode == NULL ) {
  1613. //
  1614. // we couldn't map a view for the bin containing this cell
  1615. //
  1616. return HCELL_NIL;
  1617. }
  1618. if (ARGUMENT_PRESENT(ProfileTimeout)) {
  1619. //
  1620. // Find UserWaitInterval value. This is the timeout
  1621. //
  1622. RtlInitUnicodeString(&Name, L"UserWaitInterval");
  1623. TimeoutCell = CmpFindValueByName(SystemHive,
  1624. ConfigDBNode,
  1625. &Name);
  1626. if (TimeoutCell == HCELL_NIL) {
  1627. *ProfileTimeout = 0;
  1628. } else {
  1629. TimeoutValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, TimeoutCell);
  1630. if( TimeoutValue == NULL ) {
  1631. //
  1632. // we couldn't map a view for the bin containing this cell
  1633. //
  1634. return HCELL_NIL;
  1635. }
  1636. if (TimeoutValue->Type != REG_DWORD) {
  1637. *ProfileTimeout = 0;
  1638. } else {
  1639. TempULong = (PULONG)CmpValueToData(SystemHive, TimeoutValue, &realsize);
  1640. if( TempULong == NULL ) {
  1641. //
  1642. // HvGetCell inside CmpValueToData failed; bail out safely
  1643. //
  1644. return HCELL_NIL;
  1645. }
  1646. *ProfileTimeout = *TempULong;
  1647. }
  1648. }
  1649. }
  1650. if (ARGUMENT_PRESENT(ReturnedProfileList)) {
  1651. ProfileList = *ReturnedProfileList;
  1652. //
  1653. // Enumerate the keys under IDConfigDB\Hardware Profiles
  1654. // and build the list of available hardware profiles. The list
  1655. // is built sorted by PreferenceOrder. Therefore, when the
  1656. // list is complete, the default hardware profile is at the
  1657. // head of the list.
  1658. //
  1659. RtlInitUnicodeString(&Name, L"Hardware Profiles");
  1660. ProfileCell = CmpFindSubKeyByName(SystemHive,
  1661. ConfigDBNode,
  1662. &Name);
  1663. if (ProfileCell == HCELL_NIL) {
  1664. ProfileCount = 0;
  1665. if (ProfileList != NULL) {
  1666. ProfileList->CurrentProfileCount = 0;
  1667. }
  1668. } else {
  1669. ProfileNode = (PCM_KEY_NODE)HvGetCell(SystemHive, ProfileCell);
  1670. if( ProfileNode == NULL ) {
  1671. //
  1672. // we couldn't map a view for the bin containing this cell
  1673. //
  1674. return HCELL_NIL;
  1675. }
  1676. ProfileCount = ProfileNode->SubKeyCounts[Stable];
  1677. if ((ProfileList == NULL) || (ProfileList->MaxProfileCount < ProfileCount)) {
  1678. //
  1679. // Allocate a larger ProfileList
  1680. //
  1681. ProfileList = (SystemHive->Allocate)(sizeof(CM_HARDWARE_PROFILE_LIST)
  1682. + (ProfileCount-1) * sizeof(CM_HARDWARE_PROFILE),
  1683. FALSE
  1684. ,CM_FIND_LEAK_TAG5);
  1685. if (ProfileList == NULL) {
  1686. return(HCELL_NIL);
  1687. }
  1688. ProfileList->MaxProfileCount = ProfileCount;
  1689. }
  1690. ProfileList->CurrentProfileCount = 0;
  1691. //
  1692. // Enumerate the keys and fill in the profile list.
  1693. //
  1694. for (i=0; i<ProfileCount; i++) {
  1695. CM_HARDWARE_PROFILE TempProfile;
  1696. HCELL_INDEX ValueCell;
  1697. PCM_KEY_VALUE ValueNode;
  1698. UNICODE_STRING KeyName;
  1699. ULONG realsize;
  1700. HWCell = CmpFindSubKeyByNumber(SystemHive, ProfileNode, i);
  1701. if (HWCell == HCELL_NIL) {
  1702. //
  1703. // This should never happen.
  1704. //
  1705. ProfileList->CurrentProfileCount = i;
  1706. break;
  1707. }
  1708. HWNode = (PCM_KEY_NODE)HvGetCell(SystemHive, HWCell);
  1709. if( HWNode == NULL ) {
  1710. //
  1711. // we couldn't map a view for the bin containing this cell
  1712. //
  1713. return HCELL_NIL;
  1714. }
  1715. if (HWNode->Flags & KEY_COMP_NAME) {
  1716. KeyName.Length = CmpCompressedNameSize(HWNode->Name,
  1717. HWNode->NameLength);
  1718. KeyName.MaximumLength = sizeof(NameBuf);
  1719. if (KeyName.MaximumLength < KeyName.Length) {
  1720. KeyName.Length = KeyName.MaximumLength;
  1721. }
  1722. KeyName.Buffer = NameBuf;
  1723. CmpCopyCompressedName(KeyName.Buffer,
  1724. KeyName.Length,
  1725. HWNode->Name,
  1726. HWNode->NameLength);
  1727. } else {
  1728. KeyName.Length = KeyName.MaximumLength = HWNode->NameLength;
  1729. KeyName.Buffer = HWNode->Name;
  1730. }
  1731. //
  1732. // Fill in the temporary profile structure with this
  1733. // profile's data.
  1734. //
  1735. RtlUnicodeStringToInteger(&KeyName, 0, &TempProfile.Id);
  1736. RtlInitUnicodeString(&Name, CM_HARDWARE_PROFILE_STR_PREFERENCE_ORDER);
  1737. ValueCell = CmpFindValueByName(SystemHive,
  1738. HWNode,
  1739. &Name);
  1740. if (ValueCell == HCELL_NIL) {
  1741. TempProfile.PreferenceOrder = (ULONG)-1;
  1742. } else {
  1743. ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  1744. if( ValueNode == NULL ) {
  1745. //
  1746. // we couldn't map a view for the bin containing this cell
  1747. //
  1748. return HCELL_NIL;
  1749. }
  1750. TempULong = (PULONG)CmpValueToData(SystemHive,
  1751. ValueNode,
  1752. &realsize);
  1753. if( TempULong == NULL ) {
  1754. //
  1755. // HvGetCell inside CmpValueToData failed; bail out safely
  1756. //
  1757. return HCELL_NIL;
  1758. }
  1759. TempProfile.PreferenceOrder = *TempULong;
  1760. }
  1761. RtlInitUnicodeString(&Name, CM_HARDWARE_PROFILE_STR_FRIENDLY_NAME);
  1762. ValueCell = CmpFindValueByName(SystemHive,
  1763. HWNode,
  1764. &Name);
  1765. if (ValueCell == HCELL_NIL) {
  1766. TempProfile.FriendlyName = L"-------";
  1767. TempProfile.NameLength = wcslen(TempProfile.FriendlyName) * sizeof(WCHAR);
  1768. } else {
  1769. ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  1770. if( ValueNode == NULL ) {
  1771. //
  1772. // we couldn't map a view for the bin containing this cell
  1773. //
  1774. return HCELL_NIL;
  1775. }
  1776. TempProfile.FriendlyName = (PWSTR)CmpValueToData(SystemHive,
  1777. ValueNode,
  1778. &realsize);
  1779. if( TempProfile.FriendlyName == NULL ) {
  1780. //
  1781. // HvGetCell inside CmpValueToData failed; bail out safely
  1782. //
  1783. return HCELL_NIL;
  1784. }
  1785. TempProfile.NameLength = realsize - sizeof(WCHAR);
  1786. }
  1787. TempProfile.Flags = 0;
  1788. RtlInitUnicodeString(&Name, CM_HARDWARE_PROFILE_STR_ALIASABLE);
  1789. ValueCell = CmpFindValueByName(SystemHive,
  1790. HWNode,
  1791. &Name);
  1792. if (ValueCell == HCELL_NIL) {
  1793. TempProfile.Flags = CM_HP_FLAGS_ALIASABLE;
  1794. } else {
  1795. ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  1796. if( ValueNode == NULL ) {
  1797. //
  1798. // we couldn't map a view for the bin containing this cell
  1799. //
  1800. return HCELL_NIL;
  1801. }
  1802. TempULong = (PULONG)CmpValueToData (SystemHive,ValueNode,&realsize);
  1803. if( TempULong == NULL ) {
  1804. //
  1805. // HvGetCell inside CmpValueToData failed; bail out safely
  1806. //
  1807. return HCELL_NIL;
  1808. }
  1809. if (*TempULong) {
  1810. TempProfile.Flags = CM_HP_FLAGS_ALIASABLE;
  1811. // NO other flags set.
  1812. }
  1813. }
  1814. RtlInitUnicodeString(&Name, CM_HARDWARE_PROFILE_STR_PRISTINE);
  1815. ValueCell = CmpFindValueByName(SystemHive,
  1816. HWNode,
  1817. &Name);
  1818. if (ValueCell != HCELL_NIL) {
  1819. ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  1820. if( ValueNode == NULL ) {
  1821. //
  1822. // we couldn't map a view for the bin containing this cell
  1823. //
  1824. return HCELL_NIL;
  1825. }
  1826. TempULong = (PULONG)CmpValueToData (SystemHive,ValueNode,&realsize);
  1827. if( TempULong == NULL ) {
  1828. //
  1829. // HvGetCell inside CmpValueToData failed; bail out safely
  1830. //
  1831. return HCELL_NIL;
  1832. }
  1833. if (*TempULong) {
  1834. TempProfile.Flags = CM_HP_FLAGS_PRISTINE;
  1835. // NO other flags set.
  1836. }
  1837. }
  1838. //
  1839. // If we see a profile with the ID of zero (AKA an illegal)
  1840. // ID for a hardware profile to possess, then we know that this
  1841. // must be a pristine profile.
  1842. //
  1843. if (0 == TempProfile.Id) {
  1844. TempProfile.Flags = CM_HP_FLAGS_PRISTINE;
  1845. // NO other flags set.
  1846. TempProfile.PreferenceOrder = -1; // move to the end of the list.
  1847. }
  1848. //
  1849. // Insert this new profile into the appropriate spot in the
  1850. // profile array. Entries are sorted by preference order.
  1851. //
  1852. for (j=0; j<ProfileList->CurrentProfileCount; j++) {
  1853. if (ProfileList->Profile[j].PreferenceOrder >= TempProfile.PreferenceOrder) {
  1854. //
  1855. // Insert at position j.
  1856. //
  1857. RtlMoveMemory(&ProfileList->Profile[j+1],
  1858. &ProfileList->Profile[j],
  1859. sizeof(CM_HARDWARE_PROFILE)*(ProfileList->MaxProfileCount-j-1));
  1860. break;
  1861. }
  1862. }
  1863. ProfileList->Profile[j] = TempProfile;
  1864. ++ProfileList->CurrentProfileCount;
  1865. }
  1866. }
  1867. *ReturnedProfileList = ProfileList;
  1868. }
  1869. if (ARGUMENT_PRESENT(ReturnedAliasList)) {
  1870. AliasList = *ReturnedAliasList;
  1871. //
  1872. // Enumerate the keys under IDConfigDB\Alias
  1873. // and build the list of available hardware profiles aliases.
  1874. // So that if we know our docking state we can find it in the alias
  1875. // table.
  1876. //
  1877. RtlInitUnicodeString(&Name, L"Alias");
  1878. AliasCell = CmpFindSubKeyByName(SystemHive,
  1879. ConfigDBNode,
  1880. &Name);
  1881. if (AliasCell == HCELL_NIL) {
  1882. AliasCount = 0;
  1883. if (AliasList != NULL) {
  1884. AliasList->CurrentAliasCount = 0;
  1885. }
  1886. } else {
  1887. AliasNode = (PCM_KEY_NODE)HvGetCell(SystemHive, AliasCell);
  1888. if( AliasNode == NULL ) {
  1889. //
  1890. // we couldn't map a view for the bin containing this cell
  1891. //
  1892. return HCELL_NIL;
  1893. }
  1894. AliasCount = AliasNode->SubKeyCounts[Stable];
  1895. if ((AliasList == NULL) || (AliasList->MaxAliasCount < AliasCount)) {
  1896. //
  1897. // Allocate a larger AliasList
  1898. //
  1899. AliasList = (SystemHive->Allocate)(sizeof(CM_HARDWARE_PROFILE_LIST)
  1900. + (AliasCount-1) * sizeof(CM_HARDWARE_PROFILE),
  1901. FALSE
  1902. ,CM_FIND_LEAK_TAG6);
  1903. if (AliasList == NULL) {
  1904. return(HCELL_NIL);
  1905. }
  1906. AliasList->MaxAliasCount = AliasCount;
  1907. }
  1908. AliasList->CurrentAliasCount = 0;
  1909. //
  1910. // Enumerate the keys and fill in the profile list.
  1911. //
  1912. for (i=0; i<AliasCount; i++) {
  1913. #define TempAlias AliasList->Alias[i]
  1914. HCELL_INDEX ValueCell;
  1915. PCM_KEY_VALUE ValueNode;
  1916. UNICODE_STRING KeyName;
  1917. ULONG realsize;
  1918. HWCell = CmpFindSubKeyByNumber(SystemHive, AliasNode, i);
  1919. if (HWCell == HCELL_NIL) {
  1920. //
  1921. // This should never happen.
  1922. //
  1923. AliasList->CurrentAliasCount = i;
  1924. break;
  1925. }
  1926. HWNode = (PCM_KEY_NODE)HvGetCell(SystemHive, HWCell);
  1927. if( HWNode == NULL ) {
  1928. //
  1929. // we couldn't map a view for the bin containing this cell
  1930. //
  1931. return HCELL_NIL;
  1932. }
  1933. if (HWNode->Flags & KEY_COMP_NAME) {
  1934. KeyName.Length = CmpCompressedNameSize(HWNode->Name,
  1935. HWNode->NameLength);
  1936. KeyName.MaximumLength = sizeof(NameBuf);
  1937. if (KeyName.MaximumLength < KeyName.Length) {
  1938. KeyName.Length = KeyName.MaximumLength;
  1939. }
  1940. KeyName.Buffer = NameBuf;
  1941. CmpCopyCompressedName(KeyName.Buffer,
  1942. KeyName.Length,
  1943. HWNode->Name,
  1944. HWNode->NameLength);
  1945. } else {
  1946. KeyName.Length = KeyName.MaximumLength = HWNode->NameLength;
  1947. KeyName.Buffer = HWNode->Name;
  1948. }
  1949. //
  1950. // Fill in the temporary profile structure with this
  1951. // profile's data.
  1952. //
  1953. RtlInitUnicodeString(&Name, L"ProfileNumber");
  1954. ValueCell = CmpFindValueByName(SystemHive,
  1955. HWNode,
  1956. &Name);
  1957. if (ValueCell == HCELL_NIL) {
  1958. TempAlias.ProfileNumber = 0;
  1959. } else {
  1960. ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  1961. if( ValueNode == NULL ) {
  1962. //
  1963. // we couldn't map a view for the bin containing this cell
  1964. //
  1965. return HCELL_NIL;
  1966. }
  1967. TempULong = (PULONG)CmpValueToData(SystemHive,ValueNode,&realsize);
  1968. if( TempULong == NULL ) {
  1969. //
  1970. // HvGetCell inside CmpValueToData failed; bail out safely
  1971. //
  1972. return HCELL_NIL;
  1973. }
  1974. TempAlias.ProfileNumber = *TempULong;
  1975. }
  1976. RtlInitUnicodeString(&Name, L"DockState");
  1977. ValueCell = CmpFindValueByName(SystemHive,
  1978. HWNode,
  1979. &Name);
  1980. if (ValueCell == HCELL_NIL) {
  1981. TempAlias.DockState = 0;
  1982. } else {
  1983. ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  1984. if( ValueNode == NULL ) {
  1985. //
  1986. // we couldn't map a view for the bin containing this cell
  1987. //
  1988. return HCELL_NIL;
  1989. }
  1990. TempULong = (PULONG)CmpValueToData(SystemHive,ValueNode,&realsize);
  1991. if( TempULong == NULL ) {
  1992. //
  1993. // HvGetCell inside CmpValueToData failed; bail out safely
  1994. //
  1995. return HCELL_NIL;
  1996. }
  1997. TempAlias.DockState = *TempULong;
  1998. }
  1999. RtlInitUnicodeString(&Name, L"DockID");
  2000. ValueCell = CmpFindValueByName(SystemHive,
  2001. HWNode,
  2002. &Name);
  2003. if (ValueCell == HCELL_NIL) {
  2004. TempAlias.DockID = 0;
  2005. } else {
  2006. ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  2007. if( ValueNode == NULL ) {
  2008. //
  2009. // we couldn't map a view for the bin containing this cell
  2010. //
  2011. return HCELL_NIL;
  2012. }
  2013. TempULong = (PULONG)CmpValueToData(SystemHive,ValueNode,&realsize);
  2014. if( TempULong == NULL ) {
  2015. //
  2016. // HvGetCell inside CmpValueToData failed; bail out safely
  2017. //
  2018. return HCELL_NIL;
  2019. }
  2020. TempAlias.DockID = *TempULong;
  2021. }
  2022. RtlInitUnicodeString(&Name, L"SerialNumber");
  2023. ValueCell = CmpFindValueByName(SystemHive,
  2024. HWNode,
  2025. &Name);
  2026. if (ValueCell == HCELL_NIL) {
  2027. TempAlias.SerialNumber = 0;
  2028. } else {
  2029. ValueNode = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
  2030. if( ValueNode == NULL ) {
  2031. //
  2032. // we couldn't map a view for the bin containing this cell
  2033. //
  2034. return HCELL_NIL;
  2035. }
  2036. TempULong = (PULONG)CmpValueToData(SystemHive,ValueNode,&realsize);
  2037. if( TempULong == NULL ) {
  2038. //
  2039. // HvGetCell inside CmpValueToData failed; bail out safely
  2040. //
  2041. return HCELL_NIL;
  2042. }
  2043. TempAlias.SerialNumber = *TempULong;
  2044. }
  2045. ++AliasList->CurrentAliasCount;
  2046. }
  2047. }
  2048. *ReturnedAliasList = AliasList;
  2049. }
  2050. return(IDConfigDB);
  2051. }
  2052. ULONG
  2053. CmpFindTagIndex(
  2054. IN PHHIVE Hive,
  2055. IN HCELL_INDEX TagCell,
  2056. IN HCELL_INDEX GroupOrderCell,
  2057. IN PUNICODE_STRING GroupName
  2058. )
  2059. /*++
  2060. Routine Description:
  2061. Calculates the tag index for a driver based on its tag value and
  2062. the GroupOrderList entry for its group.
  2063. Arguments:
  2064. Hive - Supplies the hive control structure for the driver.
  2065. TagCell - Supplies the cell index of the driver's tag value cell.
  2066. GroupOrderCell - Supplies the cell index for the control set's
  2067. GroupOrderList:
  2068. \Registry\Machine\System\CurrentControlSet\Control\GroupOrderList
  2069. GroupName - Supplies the name of the group the driver belongs to.
  2070. Note that if a driver's group does not have an entry under
  2071. GroupOrderList, its tags will be ignored. Also note that if
  2072. a driver belongs to no group (GroupName is NULL) its tags will
  2073. be ignored.
  2074. Return Value:
  2075. The index that the driver should be sorted by.
  2076. --*/
  2077. {
  2078. PCM_KEY_VALUE TagValue;
  2079. PCM_KEY_VALUE DriverTagValue;
  2080. HCELL_INDEX OrderCell;
  2081. PULONG OrderVector;
  2082. PULONG DriverTag;
  2083. NTSTATUS Status;
  2084. ULONG CurrentTag;
  2085. ULONG realsize;
  2086. PCM_KEY_NODE Node;
  2087. BOOLEAN BufferAllocated;
  2088. //
  2089. // no mapped hives at this point. don't bother releasing cells
  2090. //
  2091. ASSERT( Hive->ReleaseCellRoutine == NULL );
  2092. DriverTagValue = (PCM_KEY_VALUE)HvGetCell(Hive, TagCell);
  2093. if( DriverTagValue == NULL ) {
  2094. //
  2095. // we couldn't map a view for the bin containing this cell
  2096. //
  2097. return LOAD_NEXT_TO_LAST;
  2098. }
  2099. DriverTag = (PULONG)CmpValueToData(Hive, DriverTagValue, &realsize);
  2100. if( DriverTag == NULL ) {
  2101. //
  2102. // HvGetCell inside CmpValueToData failed; bail out safely
  2103. //
  2104. return LOAD_NEXT_TO_LAST;
  2105. }
  2106. Node = (PCM_KEY_NODE)HvGetCell(Hive,GroupOrderCell);
  2107. if( Node == NULL ) {
  2108. //
  2109. // we couldn't map a view for the bin containing this cell
  2110. //
  2111. return LOAD_NEXT_TO_LAST;
  2112. }
  2113. OrderCell = CmpFindValueByName(Hive,
  2114. Node,
  2115. GroupName);
  2116. if (OrderCell == HCELL_NIL) {
  2117. return(LOAD_NEXT_TO_LAST);
  2118. }
  2119. TagValue = (PCM_KEY_VALUE)HvGetCell(Hive, OrderCell);
  2120. if( TagValue == NULL ) {
  2121. //
  2122. // we couldn't map a view for the bin containing this cell
  2123. //
  2124. return LOAD_NEXT_TO_LAST;
  2125. }
  2126. CmpGetValueData(Hive,TagValue,&realsize,&OrderVector,&BufferAllocated,&OrderCell);
  2127. //OrderVector = (PULONG)CmpValueToData(Hive, TagValue,&realsize);
  2128. if( OrderVector == NULL ) {
  2129. //
  2130. // HvGetCell inside CmpValueToData failed; bail out safely
  2131. //
  2132. return LOAD_NEXT_TO_LAST;
  2133. }
  2134. for (CurrentTag=1; CurrentTag <= OrderVector[0]; CurrentTag++) {
  2135. if (OrderVector[CurrentTag] == *DriverTag) {
  2136. //
  2137. // We have found a matching tag in the OrderVector, so return
  2138. // its index.
  2139. //
  2140. #ifndef _CM_LDR_
  2141. if( BufferAllocated ) {
  2142. ExFreePool( OrderVector );
  2143. }
  2144. #endif //_CM_LDR_
  2145. return(CurrentTag);
  2146. }
  2147. }
  2148. #ifndef _CM_LDR_
  2149. if( BufferAllocated ) {
  2150. ExFreePool( OrderVector );
  2151. }
  2152. #endif //_CM_LDR_
  2153. //
  2154. // There was no matching tag in the OrderVector.
  2155. //
  2156. return(LOAD_NEXT_TO_LAST);
  2157. }
  2158. #ifdef _WANT_MACHINE_IDENTIFICATION
  2159. BOOLEAN
  2160. CmpGetBiosDateFromRegistry(
  2161. IN PHHIVE Hive,
  2162. IN HCELL_INDEX ControlSet,
  2163. OUT PUNICODE_STRING Date
  2164. )
  2165. /*++
  2166. Routine Description:
  2167. Reads and returns the BIOS date from the registry.
  2168. Arguments:
  2169. Hive - Supplies the hive control structure for the driver.
  2170. ControlSet - Supplies the HCELL_INDEX of the root cell of the hive.
  2171. Date - Receives the date string in the format "mm/dd/yy".
  2172. Return Value:
  2173. TRUE iff successful, else FALSE.
  2174. --*/
  2175. {
  2176. UNICODE_STRING name;
  2177. HCELL_INDEX control;
  2178. HCELL_INDEX biosInfo;
  2179. HCELL_INDEX valueCell;
  2180. PCM_KEY_VALUE value;
  2181. ULONG realSize;
  2182. PCM_KEY_NODE Node;
  2183. //
  2184. // no mapped hives at this point. don't bother releasing cells
  2185. //
  2186. ASSERT( Hive->ReleaseCellRoutine == NULL );
  2187. //
  2188. // Find CONTROL node
  2189. //
  2190. Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlSet);
  2191. if( Node == NULL ) {
  2192. //
  2193. // we couldn't map a view for the bin containing this cell
  2194. //
  2195. return FALSE;
  2196. }
  2197. RtlInitUnicodeString(&name, L"Control");
  2198. control = CmpFindSubKeyByName( Hive,
  2199. Node,
  2200. &name);
  2201. if (control == HCELL_NIL) {
  2202. return(FALSE);
  2203. }
  2204. //
  2205. // Find BIOSINFO node
  2206. //
  2207. Node = (PCM_KEY_NODE)HvGetCell(Hive, control);
  2208. if( Node == NULL ) {
  2209. //
  2210. // we couldn't map a view for the bin containing this cell
  2211. //
  2212. return FALSE;
  2213. }
  2214. RtlInitUnicodeString(&name, L"BIOSINFO");
  2215. biosInfo = CmpFindSubKeyByName( Hive,
  2216. Node,
  2217. &name);
  2218. if (biosInfo == HCELL_NIL) {
  2219. return(FALSE);
  2220. }
  2221. //
  2222. // Find SystemBiosDate value
  2223. //
  2224. Node = (PCM_KEY_NODE)HvGetCell(Hive, biosInfo);
  2225. if( Node == NULL ) {
  2226. //
  2227. // we couldn't map a view for the bin containing this cell
  2228. //
  2229. return FALSE;
  2230. }
  2231. RtlInitUnicodeString(&name, L"SystemBiosDate");
  2232. valueCell = CmpFindValueByName( Hive,
  2233. Node,
  2234. &name);
  2235. if (valueCell == HCELL_NIL) {
  2236. return(FALSE);
  2237. }
  2238. value = (PCM_KEY_VALUE)HvGetCell(Hive, valueCell);
  2239. if( value == NULL ) {
  2240. //
  2241. // we couldn't map a view for the bin containing this cell
  2242. //
  2243. return FALSE;
  2244. }
  2245. Date->Buffer = (PWSTR)CmpValueToData(Hive, value, &realSize);
  2246. if( Date->Buffer == NULL ) {
  2247. //
  2248. // we couldn't map a view for the bin containing this cell
  2249. //
  2250. return FALSE;
  2251. }
  2252. Date->MaximumLength=(USHORT)realSize;
  2253. Date->Length = 0;
  2254. while ( (Date->Length < Date->MaximumLength) &&
  2255. (Date->Buffer[Date->Length/sizeof(WCHAR)] != UNICODE_NULL)) {
  2256. Date->Length += sizeof(WCHAR);
  2257. }
  2258. return (TRUE);
  2259. }
  2260. BOOLEAN
  2261. CmpGetBiosinfoFileNameFromRegistry(
  2262. IN PHHIVE Hive,
  2263. IN HCELL_INDEX ControlSet,
  2264. OUT PUNICODE_STRING InfName
  2265. )
  2266. {
  2267. UNICODE_STRING name;
  2268. HCELL_INDEX control;
  2269. HCELL_INDEX biosInfo;
  2270. HCELL_INDEX valueCell;
  2271. PCM_KEY_VALUE value;
  2272. ULONG realSize;
  2273. PCM_KEY_NODE Node;
  2274. //
  2275. // no mapped hives at this point. don't bother releasing cells
  2276. //
  2277. ASSERT( Hive->ReleaseCellRoutine == NULL );
  2278. //
  2279. // Find CONTROL node
  2280. //
  2281. Node = (PCM_KEY_NODE)HvGetCell(Hive, ControlSet);
  2282. if( Node == NULL ) {
  2283. //
  2284. // we couldn't map a view for the bin containing this cell
  2285. //
  2286. return FALSE;
  2287. }
  2288. RtlInitUnicodeString(&name, L"Control");
  2289. control = CmpFindSubKeyByName( Hive,
  2290. Node,
  2291. &name);
  2292. if (control == HCELL_NIL) {
  2293. return(FALSE);
  2294. }
  2295. //
  2296. // Find BIOSINFO node
  2297. //
  2298. Node = (PCM_KEY_NODE)HvGetCell(Hive, control);
  2299. if( Node == NULL ) {
  2300. //
  2301. // we couldn't map a view for the bin containing this cell
  2302. //
  2303. return FALSE;
  2304. }
  2305. RtlInitUnicodeString(&name, L"BIOSINFO");
  2306. biosInfo = CmpFindSubKeyByName( Hive,
  2307. Node,
  2308. &name);
  2309. if (biosInfo == HCELL_NIL) {
  2310. return(FALSE);
  2311. }
  2312. //
  2313. // Find InfName value
  2314. //
  2315. Node = (PCM_KEY_NODE)HvGetCell(Hive, biosInfo);
  2316. if( Node == NULL ) {
  2317. //
  2318. // we couldn't map a view for the bin containing this cell
  2319. //
  2320. return FALSE;
  2321. }
  2322. RtlInitUnicodeString(&name, L"InfName");
  2323. valueCell = CmpFindValueByName( Hive,
  2324. Node,
  2325. &name);
  2326. if (valueCell == HCELL_NIL) {
  2327. return(FALSE);
  2328. }
  2329. value = (PCM_KEY_VALUE)HvGetCell(Hive, valueCell);
  2330. if( value == NULL ) {
  2331. //
  2332. // we couldn't map a view for the bin containing this cell
  2333. //
  2334. return FALSE;
  2335. }
  2336. InfName->Buffer = (PWSTR)CmpValueToData(Hive, value, &realSize);
  2337. if( InfName->Buffer == NULL ) {
  2338. //
  2339. // we couldn't map a view for the bin containing this cell
  2340. //
  2341. return FALSE;
  2342. }
  2343. InfName->MaximumLength=(USHORT)realSize;
  2344. InfName->Length = 0;
  2345. while ( (InfName->Length < InfName->MaximumLength) &&
  2346. (InfName->Buffer[InfName->Length/sizeof(WCHAR)] != UNICODE_NULL)) {
  2347. InfName->Length += sizeof(WCHAR);
  2348. }
  2349. return (TRUE);
  2350. }
  2351. #endif