Leaked source code of windows server 2003
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.

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