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.

3085 lines
85 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. regboot.c
  5. Abstract:
  6. Provides a minimal registry implementation designed to be used by the
  7. osloader at boot time. This includes loading the system hive
  8. ( <SystemRoot>\config\SYSTEM ) into memory, and computing the driver
  9. load list from it.
  10. Author:
  11. John Vert (jvert) 10-Mar-1992
  12. Revision History:
  13. Doug Fritz (dFritz) 07-Oct-1997 & KenRay Feb 98
  14. - Filter hardware profiles based on detected hardware
  15. configuration (docking station) information
  16. --*/
  17. #include "bldr.h"
  18. #include "msg.h"
  19. #include "cmp.h"
  20. #include "stdio.h"
  21. #include "string.h"
  22. #include <dockinfo.h>
  23. #include <netboot.h>
  24. #ifdef i386
  25. #include "bldrx86.h"
  26. #endif
  27. #if defined(_IA64_)
  28. #include "bldria64.h"
  29. #endif
  30. #ifdef _WANT_MACHINE_IDENTIFICATION
  31. #include <stdlib.h>
  32. #include <ntverp.h>
  33. #endif
  34. #include "bldrint.h"
  35. #include "vmode.h"
  36. #define MAX_DRIVER_NAME_LENGTH 64
  37. CMHIVE BootHive;
  38. ULONG CmLogLevel=100;
  39. ULONG CmLogSelect=0;
  40. ULONG ScreenWidth=80;
  41. #ifdef EFI
  42. ULONG ScreenHeight=24;
  43. #else
  44. ULONG ScreenHeight=25;
  45. #endif
  46. ULONG LkgStartTime;
  47. //
  48. // used by the advanced boot screen to force a LKG boot
  49. //
  50. BOOLEAN ForceLastKnownGood;
  51. //
  52. // Variable used to check whether to display
  53. // "Return to OS Choices Menu" or not in adv. boot
  54. //
  55. BOOLEAN BlShowReturnToOSChoices = TRUE;
  56. VOID
  57. BlRedrawProgressBar(
  58. VOID
  59. );
  60. VOID
  61. BlOutputStartupMsg(
  62. ULONG uMsgID
  63. );
  64. ULONG
  65. BlGetAdvancedBootID(
  66. LONG BootOption
  67. );
  68. //
  69. // Private function prototypes
  70. //
  71. BOOLEAN
  72. BlInitializeHive(
  73. IN PVOID HiveImage,
  74. IN PCMHIVE Hive,
  75. IN BOOLEAN IsAlternate
  76. );
  77. BOOLEAN
  78. BlpCheckRestartSetup(
  79. VOID
  80. );
  81. PVOID
  82. BlpHiveAllocate(
  83. IN ULONG Length,
  84. IN BOOLEAN UseForIo,
  85. ULONG Tag
  86. );
  87. VOID
  88. BlDockInfoFilterProfileList(
  89. IN OUT PCM_HARDWARE_PROFILE_LIST ProfileList,
  90. IN OUT PCM_HARDWARE_PROFILE_ALIAS_LIST AliasList
  91. );
  92. VOID
  93. BlStartConfigPrompt(
  94. VOID
  95. )
  96. /*++
  97. Routine Description:
  98. This routine displays the LKG prompt, records the current time,
  99. and returns. The prompt is displayed before the kernel and HAL
  100. are loaded, and then removed afterwards.
  101. Arguments:
  102. None.
  103. Return Value:
  104. None.
  105. --*/
  106. {
  107. // ULONG Count;
  108. PTCHAR LkgPrompt;
  109. LkgPrompt = BlFindMessage(BL_LKG_MENU_PROMPT);
  110. if (LkgPrompt==NULL) {
  111. return;
  112. }
  113. //
  114. // display LKG prompt
  115. //
  116. #if 0
  117. BlPositionCursor(1,3);
  118. ArcWrite(BlConsoleOutDeviceId,
  119. LkgPrompt,
  120. _tcslen(LkgPrompt)*sizeof(TCHAR),
  121. &Count);
  122. BlPositionCursor(1,2);
  123. #endif
  124. LkgStartTime = ArcGetRelativeTime();
  125. #if defined(REMOTE_BOOT) && defined(i386)
  126. //
  127. // Wait to allow the user to type space or F8. If anything is typed then behave
  128. // conservatively and load the kernel, etc., from the server just in case CSC or
  129. // the local filesystem is broken.
  130. //
  131. if (BlBootingFromNet) {
  132. ULONG EndTime;
  133. ULONG Status;
  134. ULONG CurrentTime;
  135. EndTime = LkgStartTime + 3;
  136. if (EndTime <= ArcGetRelativeTime()) {
  137. EndTime = ArcGetRelativeTime()+1;
  138. }
  139. do {
  140. if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
  141. //
  142. // There is a key pending, assume it is CSC related. If it isn't
  143. // CSC then it just means we laod a few extra files from the
  144. // server.
  145. //
  146. NetBootCSC = FALSE;
  147. break;
  148. }
  149. CurrentTime = ArcGetRelativeTime();
  150. //
  151. // Terminate the loop if the EndTime has been reached, or
  152. // if the CurrentTime has wrapped at midnight.
  153. //
  154. } while ((CurrentTime < EndTime) &&
  155. (CurrentTime >= LkgStartTime));
  156. }
  157. #endif // defined(REMOTE_BOOT) && defined(i386)
  158. }
  159. BOOLEAN
  160. BlEndConfigPrompt(
  161. VOID
  162. )
  163. /*++
  164. Routine Description:
  165. This routine waits until the LKG timeout has expired or the
  166. user presses a key and then removes the LKG prompt.
  167. Arguments:
  168. None.
  169. Return Value:
  170. TRUE - Space bar pressed.
  171. FALSE - Space bar was not pressed.
  172. --*/
  173. {
  174. ULONG EndTime;
  175. ULONG Key;
  176. ULONG CurrentTime;
  177. #if defined(EFI)
  178. ULONGLONG OriginalInputTimeout;
  179. #endif
  180. //
  181. // We do not wait for a keypress if there is not already one.
  182. //
  183. EndTime = 0;
  184. if( BlIsTerminalConnected() ) {
  185. //
  186. // If we're booting headless, give the user lots of time
  187. // to press any of the advanced options keys.
  188. //
  189. EndTime = ArcGetRelativeTime() + 5;
  190. }
  191. #if defined(EFI)
  192. //
  193. // on certain machines the boot manager will
  194. // reset ConIn and the usb keyboard is still
  195. // reinitialize when we get here. add a short
  196. // timeout period to BlGetKey() that will
  197. // give the necessary time required for
  198. // for interface to behave properly.
  199. //
  200. OriginalInputTimeout = BlGetInputTimeout();
  201. if (EndTime) {
  202. BlSetInputTimeout(50000000); // 5 seconds
  203. }
  204. else {
  205. BlSetInputTimeout(10000000); // 1 second
  206. }
  207. #endif
  208. #if defined(REMOTE_BOOT) && defined(i386)
  209. //
  210. // If a key was detected and CSC turned off then re-enable CSC until
  211. // we find out if it should be disabled for this whole boot.
  212. //
  213. NetBootCSC = TRUE;
  214. #endif // defined(REMOTE_BOOT) && defined(i386)
  215. do {
  216. LONG AdvancedBoot = -1;
  217. BOOLEAN bOldState = BlShowReturnToOSChoices;
  218. if ((Key = BlGetKey()) != 0) {
  219. //
  220. // return if the pending key was the spacebar.
  221. //
  222. if (Key == ' ') {
  223. #if defined(EFI)
  224. BlSetInputTimeout(OriginalInputTimeout);
  225. #endif
  226. return(TRUE);
  227. }
  228. //
  229. // look to see if the user pressed the F5 or F8 keys,
  230. // these keys trigger the advanced boot menu. the advanced
  231. // boot menu can also be entered from the main boot menu by
  232. // pressing the same keys.
  233. //
  234. if (Key == F5_KEY || Key == F8_KEY) {
  235. //
  236. // present the menu and get the user's request
  237. //
  238. BlShowReturnToOSChoices = FALSE;
  239. if (DisplayLogoOnBoot) {
  240. if (!DbcsLangId)
  241. HW_CURSOR(0x80000000,0x3);
  242. else
  243. HW_CURSOR(0x80000000,0x12);
  244. }
  245. AdvancedBoot = BlDoAdvancedBoot( BL_ADVANCEDBOOT_TITLE, 0, FALSE, 0 );
  246. if (DisplayLogoOnBoot) {
  247. PSTR BootOption;
  248. if ((AdvancedBoot != -1) &&
  249. ((BootOption = BlGetAdvancedBootLoadOptions(AdvancedBoot)) != NULL ) &&
  250. (!strncmp("SAFEBOOT",BootOption,8))) {
  251. DisplayLogoOnBoot = FALSE; // on safe boot let the "Checking file system" message
  252. // appear as it appears today (in graphics mode)
  253. } else {
  254. #ifndef EFI
  255. HW_CURSOR(0x80000000,0x12);
  256. if (DbcsLangId)
  257. TextClearDisplay();
  258. VgaEnableVideo();
  259. PaletteOn();
  260. DrawBitmap ();
  261. BlUpdateBootStatus();
  262. #endif
  263. }
  264. }
  265. BlShowReturnToOSChoices = bOldState;
  266. if (AdvancedBoot != -1) {
  267. //
  268. // they chose a valid boot option so append
  269. // any os load options and perform any necessary
  270. // option processing.
  271. //
  272. PSTR NewOptions = BlGetAdvancedBootLoadOptions(AdvancedBoot);
  273. if( BlGetAdvancedBootID(AdvancedBoot) == BL_MSG_REBOOT ) {
  274. BlClearScreen();
  275. ArcReboot();
  276. }
  277. if (NewOptions != NULL && strstr(BlLoaderBlock->LoadOptions,NewOptions) == NULL) {
  278. ULONG len = (ULONG)strlen(NewOptions) + // new options
  279. 1 + // seperated by a space
  280. (ULONG)strlen(BlLoaderBlock->LoadOptions) + // old options
  281. 1; // null terminator
  282. NewOptions = BlAllocateHeap(len * sizeof(UCHAR));
  283. strcpy(NewOptions,BlLoaderBlock->LoadOptions);
  284. strcat(NewOptions," ");
  285. strcat(NewOptions,BlGetAdvancedBootLoadOptions(AdvancedBoot));
  286. BlLoaderBlock->LoadOptions = NewOptions;
  287. DBGTRACE(TEXT("Load Options = %S"), BlLoaderBlock->LoadOptions);
  288. }
  289. BlDoAdvancedBootLoadProcessing(AdvancedBoot);
  290. }
  291. }
  292. }
  293. CurrentTime = ArcGetRelativeTime();
  294. //
  295. // Terminate the loop if the EndTime has been reached, or
  296. // if the CurrentTime has wrapped at midnight.
  297. //
  298. } while ((CurrentTime < EndTime) &&
  299. (CurrentTime >= LkgStartTime));
  300. #if defined(EFI)
  301. BlSetInputTimeout(OriginalInputTimeout);
  302. #endif
  303. //
  304. // make LKG prompt go away, so as not to startle the user.
  305. // remote the trailer & update progress bar
  306. //
  307. #if defined(_IA64_)
  308. BlOutputStartupMsg(BL_MSG_STARTING_WINDOWS);
  309. #endif
  310. BlRedrawProgressBar();
  311. return(FALSE);
  312. }
  313. VOID
  314. BlpSwitchControlSet(
  315. OUT PCM_HARDWARE_PROFILE_LIST *ProfileList,
  316. OUT PCM_HARDWARE_PROFILE_ALIAS_LIST *AliasList,
  317. IN BOOLEAN UseLastKnownGood,
  318. OUT PHCELL_INDEX ControlSet
  319. )
  320. /*++
  321. Routine Description:
  322. Switches the current control set to the specified control
  323. set and rebuilds the hardware profile list.
  324. Arguments:
  325. ProfileList - Returns the new hardware profile list
  326. UseLastKnownGood - Supplies whether the LKG control set is to be used.
  327. ControlSet - Returns the HCELL_INDEX of the new control set.
  328. Return Value:
  329. None.
  330. --*/
  331. {
  332. UNICODE_STRING ControlName;
  333. HCELL_INDEX NewControlSet;
  334. BOOLEAN AutoSelect; // ignored
  335. //
  336. // Find the new control set.
  337. //
  338. if (UseLastKnownGood) {
  339. RtlInitUnicodeString(&ControlName, L"LastKnownGood");
  340. } else {
  341. RtlInitUnicodeString(&ControlName, L"Default");
  342. }
  343. NewControlSet = CmpFindControlSet(&BootHive.Hive,
  344. BootHive.Hive.BaseBlock->RootCell,
  345. &ControlName,
  346. &AutoSelect);
  347. if (NewControlSet == HCELL_NIL) {
  348. return;
  349. }
  350. CmpFindProfileOption(&BootHive.Hive,
  351. NewControlSet,
  352. ProfileList,
  353. AliasList,
  354. NULL);
  355. *ControlSet = NewControlSet;
  356. }
  357. ULONG
  358. BlCountLines(
  359. IN PTCHAR Lines
  360. )
  361. /*++
  362. Routine Description:
  363. Counts the number of lines in the given string.
  364. Arguments:
  365. Lines - Supplies a pointer to the start of the string
  366. Return Value:
  367. The number of lines in the string.
  368. --*/
  369. {
  370. PTCHAR p;
  371. ULONG NumLines = 0;
  372. p=Lines;
  373. while (*p != TEXT('\0')) {
  374. if ((*p == TEXT('\r')) && (*(p+1) == TEXT('\n'))) {
  375. ++NumLines;
  376. ++p; // move forward to \n
  377. }
  378. ++p;
  379. }
  380. return(NumLines);
  381. }
  382. BOOLEAN
  383. BlConfigMenuPrompt(
  384. IN ULONG Timeout,
  385. IN OUT PBOOLEAN UseLastKnownGood,
  386. IN OUT PHCELL_INDEX ControlSet,
  387. OUT PCM_HARDWARE_PROFILE_LIST *ProfileList,
  388. OUT PCM_HARDWARE_PROFILE_ALIAS_LIST *AliasList,
  389. OUT PCM_HARDWARE_PROFILE *HardwareProfile
  390. )
  391. /*++
  392. Routine Description:
  393. This routine provides the user-interface for the configuration menu.
  394. The prompt is given if the user hits the break-in key, or if the
  395. LastKnownGood environment variable is TRUE and AutoSelect is FALSE, or
  396. if the timeout value on the hardware profile configuration is non-zero
  397. Arguments:
  398. Timeout - Supplies the timeout value for the menu. -1 or 0 implies the menu
  399. will never timeout.
  400. UseLastKnownGood - Returns the LastKnownGood setting that should be
  401. used for the boot.
  402. ControlSet - Returns the control set (either Default or LKG)
  403. ProfileList - Supplies the default list of profiles.
  404. Returns the current list of profiles.
  405. (may change due to switching to/from the LKG controlset)
  406. HardwareProfile - Returns the hardware profile that should be used.
  407. Return Value:
  408. TRUE - Boot should proceed.
  409. FALSE - The user has chosen to return to the firmware menu/flexboot menu.
  410. --*/
  411. {
  412. ULONG HeaderLines;
  413. ULONG TrailerLines;
  414. ULONG i;
  415. ULONG Count;
  416. ULONG flags;
  417. ULONG Key;
  418. PTCHAR MenuHeader;
  419. PTCHAR MenuTrailer1;
  420. PTCHAR MenuTrailer2;
  421. PTCHAR p;
  422. #ifndef UNICODE
  423. ULONG OptionLength;
  424. #endif
  425. TCHAR MenuOption[80];
  426. PCM_HARDWARE_PROFILE Profile;
  427. ULONG ProfileCount;
  428. _TUCHAR LkgMnemonic;
  429. _TUCHAR DefaultMnemonic;
  430. PTCHAR Temp;
  431. ULONG DisplayLines;
  432. ULONG TopProfileLine=0;
  433. ULONG CurrentSelection = 0;
  434. ULONG CurrentProfile;
  435. ULONG EndTime = 0;
  436. ULONG CurrentTime = 0;
  437. PTCHAR TimeoutPrompt;
  438. UNREFERENCED_PARAMETER( HardwareProfile );
  439. if ((Timeout != (ULONG)-1) && (Timeout != 0)) {
  440. CurrentTime = ArcGetRelativeTime();
  441. EndTime = CurrentTime + Timeout;
  442. TimeoutPrompt = BlFindMessage(BL_LKG_TIMEOUT);
  443. if (TimeoutPrompt != NULL) {
  444. p=_tcschr(TimeoutPrompt, TEXT('\n'));
  445. if (p) {
  446. *p = TEXT('\0');
  447. }
  448. p=_tcschr(TimeoutPrompt, TEXT('\r'));
  449. if (p) {
  450. *p = TEXT('\0');
  451. }
  452. }
  453. } else {
  454. TimeoutPrompt = NULL;
  455. }
  456. MenuHeader = BlFindMessage(BL_LKG_MENU_HEADER);
  457. Temp = BlFindMessage(BL_LKG_SELECT_MNEMONIC);
  458. if (Temp == NULL) {
  459. return(TRUE);
  460. }
  461. LkgMnemonic = (_TUCHAR)_totupper(Temp[0]);
  462. Temp = BlFindMessage(BL_DEFAULT_SELECT_MNEMONIC);
  463. if (Temp == NULL) {
  464. return(TRUE);
  465. }
  466. DefaultMnemonic = (_TUCHAR)_totupper(Temp[0]);
  467. if ((*UseLastKnownGood) &&
  468. (*ProfileList) && ((*ProfileList)->CurrentProfileCount == 1)) {
  469. //
  470. // The user selected last known good via boot.ini/nvram/etc. Since this
  471. // was a concious decision, and we don't have more than one profile to
  472. // choose, just skip this UI altogether.
  473. //
  474. ASSERT(CurrentSelection == 0);
  475. return TRUE;
  476. }
  477. Restart:
  478. if (*ProfileList == NULL) {
  479. ProfileCount = 0;
  480. } else {
  481. ProfileCount = (*ProfileList)->CurrentProfileCount;
  482. }
  483. if (ProfileCount == 0) {
  484. MenuTrailer1 = BlFindMessage(BL_LKG_MENU_TRAILER_NO_PROFILES);
  485. } else {
  486. MenuTrailer1 = BlFindMessage(BL_LKG_MENU_TRAILER);
  487. }
  488. if (*UseLastKnownGood) {
  489. MenuTrailer2 = BlFindMessage(BL_SWITCH_DEFAULT_TRAILER);
  490. } else {
  491. MenuTrailer2 = BlFindMessage(BL_SWITCH_LKG_TRAILER);
  492. }
  493. if ((MenuHeader==NULL) || (MenuTrailer1==NULL) || (MenuTrailer2==NULL)) {
  494. return(TRUE);
  495. }
  496. //
  497. // strip trailing /r/n from MenuTrailer2 to prevent it from scrolling
  498. // the screen when we output it.
  499. //
  500. #if 0
  501. p=MenuTrailer2 + strlen(MenuTrailer2) - 1;
  502. while ((*p == TEXT('\r')) || (*p == TEXT('\n'))) {
  503. *p = TEXT('\0');
  504. --p;
  505. }
  506. #endif
  507. BlClearScreen();
  508. #ifdef EFI
  509. BlEfiSetAttribute( DEFATT );
  510. #else
  511. BlSetInverseMode(FALSE);
  512. #endif
  513. //
  514. // Count the number of lines in the header.
  515. //
  516. HeaderLines=BlCountLines(MenuHeader);
  517. //
  518. // Display the menu header.
  519. //
  520. ArcWrite(BlConsoleOutDeviceId,
  521. MenuHeader,
  522. (ULONG)_tcslen(MenuHeader)*sizeof(TCHAR),
  523. &Count);
  524. //
  525. // Count the number of lines in the trailer.
  526. //
  527. TrailerLines=BlCountLines(MenuTrailer1) + BlCountLines(MenuTrailer2);
  528. //
  529. // Display the trailing prompt.
  530. //
  531. if (TimeoutPrompt) {
  532. TrailerLines += 1;
  533. }
  534. BlPositionCursor(1, ScreenHeight-TrailerLines);
  535. ArcWrite(BlConsoleOutDeviceId,
  536. MenuTrailer1,
  537. (ULONG)_tcslen(MenuTrailer1)*sizeof(TCHAR),
  538. &Count);
  539. ArcWrite(BlConsoleOutDeviceId,
  540. MenuTrailer2,
  541. (ULONG)_tcslen(MenuTrailer2)*sizeof(TCHAR),
  542. &Count);
  543. //
  544. // Compute number of selections that can be displayed
  545. //
  546. DisplayLines = ScreenHeight-HeaderLines-TrailerLines-3;
  547. if (ProfileCount < DisplayLines) {
  548. DisplayLines = ProfileCount;
  549. }
  550. //
  551. // Start menu selection loop.
  552. //
  553. do {
  554. if (ProfileCount > 0) {
  555. //
  556. // Display options with current selection highlighted
  557. //
  558. for (i=0; i < DisplayLines; i++) {
  559. CurrentProfile = i+TopProfileLine;
  560. Profile = &(*ProfileList)->Profile[CurrentProfile];
  561. BlPositionCursor(5, HeaderLines+i+2);
  562. #ifdef EFI
  563. BlEfiSetAttribute( (CurrentProfile == CurrentSelection) ? INVATT : DEFATT );
  564. #else
  565. BlSetInverseMode((BOOLEAN)(CurrentProfile == CurrentSelection));
  566. #endif
  567. #ifdef UNICODE
  568. ArcWrite(BlConsoleOutDeviceId,
  569. Profile->FriendlyName,
  570. Profile->NameLength,
  571. &Count );
  572. #else
  573. RtlUnicodeToMultiByteN(MenuOption,
  574. sizeof(MenuOption),
  575. &OptionLength,
  576. Profile->FriendlyName,
  577. Profile->NameLength);
  578. ArcWrite(BlConsoleOutDeviceId,
  579. MenuOption,
  580. OptionLength,
  581. &Count);
  582. #endif
  583. #ifdef EFI
  584. BlEfiSetAttribute( DEFATT );
  585. #else
  586. BlSetInverseMode(FALSE);
  587. #endif
  588. BlClearToEndOfLine();
  589. }
  590. } else {
  591. //
  592. // No profile options available, just display the default
  593. // highlighted to indicate that ENTER will start the system.
  594. //
  595. Temp = BlFindMessage(BL_BOOT_DEFAULT_PROMPT);
  596. if (Temp != NULL) {
  597. BlPositionCursor(5, HeaderLines+3);
  598. #ifdef EFI
  599. BlEfiSetAttribute( INVATT );
  600. #else
  601. BlSetInverseMode(TRUE);
  602. #endif
  603. ArcWrite(BlConsoleOutDeviceId,
  604. Temp,
  605. (ULONG)_tcslen(Temp)*sizeof(TCHAR),
  606. &Count);
  607. #ifdef EFI
  608. BlEfiSetAttribute( INVATT );
  609. #else
  610. BlSetInverseMode(TRUE);
  611. #endif
  612. }
  613. }
  614. if (TimeoutPrompt) {
  615. CurrentTime = ArcGetRelativeTime();
  616. _stprintf(MenuOption, TimeoutPrompt, EndTime-CurrentTime);
  617. BlPositionCursor(1, ScreenHeight);
  618. ArcWrite(BlConsoleOutDeviceId,
  619. MenuOption,
  620. (ULONG)_tcslen(MenuOption)*sizeof(TCHAR),
  621. &Count);
  622. BlClearToEndOfLine();
  623. }
  624. //
  625. // Loop waiting for keypress or time change.
  626. //
  627. do {
  628. if ((Key = BlGetKey()) != 0) {
  629. TimeoutPrompt = NULL; // turn off timeout prompt
  630. BlPositionCursor(1,ScreenHeight);
  631. BlClearToEndOfLine();
  632. break;
  633. }
  634. if (TimeoutPrompt) {
  635. if (ArcGetRelativeTime() != CurrentTime) {
  636. //
  637. // Time has changed, update the countdown and check for timeout
  638. //
  639. CurrentTime = ArcGetRelativeTime();
  640. _stprintf(MenuOption, TimeoutPrompt, EndTime-CurrentTime);
  641. BlPositionCursor(1, ScreenHeight);
  642. ArcWrite(BlConsoleOutDeviceId,
  643. MenuOption,
  644. (ULONG)_tcslen(MenuOption)*sizeof(TCHAR),
  645. &Count);
  646. BlClearToEndOfLine();
  647. if (EndTime == CurrentTime) {
  648. goto ProcessSelection;
  649. }
  650. }
  651. }
  652. } while ( TRUE );
  653. switch (Key) {
  654. case UP_ARROW:
  655. //
  656. // Cursor up
  657. //
  658. if (ProfileCount > 0) {
  659. if (CurrentSelection==0) {
  660. CurrentSelection = ProfileCount - 1;
  661. if (TopProfileLine + DisplayLines <= CurrentSelection) {
  662. TopProfileLine = CurrentSelection - DisplayLines + 1;
  663. }
  664. } else {
  665. if (--CurrentSelection < TopProfileLine) {
  666. //
  667. // Scroll up
  668. //
  669. TopProfileLine = CurrentSelection;
  670. }
  671. }
  672. }
  673. break;
  674. case DOWN_ARROW:
  675. //
  676. // Cursor down
  677. //
  678. if (ProfileCount > 0) {
  679. CurrentSelection = (CurrentSelection+1) % ProfileCount;
  680. if (CurrentSelection == 0) {
  681. TopProfileLine = 0;
  682. } else if (TopProfileLine + DisplayLines <= CurrentSelection) {
  683. TopProfileLine = CurrentSelection - DisplayLines + 1;
  684. }
  685. }
  686. break;
  687. case F3_KEY:
  688. //
  689. // F3
  690. //
  691. *ControlSet = HCELL_NIL;
  692. return(FALSE);
  693. default:
  694. //
  695. // Check to see if the Key indicates the user selection LKG
  696. // first, we have to make sure we are looking at an alpha char.
  697. //
  698. if ( ((Key >> 8) == 0) && _istalpha((TCHAR)Key) ) {
  699. if ((_totupper((TCHAR)Key) == LkgMnemonic) && (*UseLastKnownGood == FALSE)) {
  700. *UseLastKnownGood = TRUE;
  701. BlpSwitchControlSet(ProfileList,
  702. AliasList,
  703. TRUE,
  704. ControlSet);
  705. if (NULL != *ProfileList) {
  706. if ((*ProfileList)->CurrentProfileCount > 0) {
  707. BlDockInfoFilterProfileList (*ProfileList, *AliasList);
  708. }
  709. }
  710. goto Restart;
  711. //
  712. // regenerate profile list here
  713. //
  714. } else if ((_totupper((TCHAR)Key) == DefaultMnemonic) && (*UseLastKnownGood)) {
  715. *UseLastKnownGood = FALSE;
  716. BlpSwitchControlSet(ProfileList,
  717. AliasList,
  718. FALSE,
  719. ControlSet);
  720. if (NULL != *ProfileList) {
  721. if ((*ProfileList)->CurrentProfileCount > 0) {
  722. BlDockInfoFilterProfileList (*ProfileList, *AliasList);
  723. }
  724. }
  725. goto Restart;
  726. }
  727. }
  728. break;
  729. } // switch
  730. } while ( (Key != ASCII_CR) && (Key != ASCII_LF) );
  731. ProcessSelection:
  732. if (ProfileCount > 0) {
  733. if (HW_PROFILE_STATUS_SUCCESS == BlLoaderBlock->Extension->Profile.Status) {
  734. flags = ((*ProfileList)->Profile[CurrentSelection].Flags);
  735. if (flags & CM_HP_FLAGS_PRISTINE) {
  736. BlLoaderBlock->Extension->Profile.Status =
  737. HW_PROFILE_STATUS_PRISTINE_MATCH;
  738. } else if (flags & CM_HP_FLAGS_TRUE_MATCH) {
  739. BlLoaderBlock->Extension->Profile.Status =
  740. HW_PROFILE_STATUS_TRUE_MATCH;
  741. } else if (flags & CM_HP_FLAGS_ALIASABLE) {
  742. BlLoaderBlock->Extension->Profile.Status =
  743. HW_PROFILE_STATUS_ALIAS_MATCH;
  744. }
  745. }
  746. CmpSetCurrentProfile(&BootHive.Hive,
  747. *ControlSet,
  748. &(*ProfileList)->Profile[CurrentSelection]);
  749. }
  750. return(TRUE);
  751. }
  752. ARC_STATUS
  753. BlLoadBootDrivers(
  754. IN PPATH_SET DefaultPathSet,
  755. IN PLIST_ENTRY BootDriverListHead,
  756. OUT PCHAR BadFileName
  757. )
  758. /*++
  759. Routine Description:
  760. Walks the boot driver list and loads all the drivers
  761. Arguments:
  762. DefaultPathSet - Describes the possible locations drivers could be loaded
  763. from.
  764. BootDriverListHead - Supplies the head of the boot driver list
  765. BadFileName - Returns the filename of the critical driver that
  766. did not load. Not valid if ESUCCESS is returned.
  767. Return Value:
  768. ESUCCESS is returned if all the boot drivers were successfully loaded.
  769. Otherwise, an unsuccessful status is returned.
  770. --*/
  771. {
  772. ULONG DeviceId = 0;
  773. PBOOT_DRIVER_NODE DriverNode;
  774. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  775. PLIST_ENTRY NextEntry;
  776. CHAR DriverName[MAX_DRIVER_NAME_LENGTH];
  777. PCHAR NameStart;
  778. CHAR DriverDevice[128];
  779. CHAR DriverPath[128];
  780. ARC_STATUS Status;
  781. UNICODE_STRING DeviceName;
  782. UNICODE_STRING FileName;
  783. WCHAR SystemRootBuffer[] = L"\\SystemRoot\\";
  784. ULONG SystemRootLength;
  785. PWSTR p;
  786. ULONG Index;
  787. BOOLEAN AbsolutePath;
  788. FULL_PATH_SET LocalPathSet;
  789. PPATH_SOURCE PathSource;
  790. SystemRootLength = (ULONG)wcslen(SystemRootBuffer);
  791. NextEntry = BootDriverListHead->Flink;
  792. while (NextEntry != BootDriverListHead) {
  793. DriverNode = CONTAINING_RECORD(NextEntry,
  794. BOOT_DRIVER_NODE,
  795. ListEntry.Link);
  796. Status = ESUCCESS;
  797. DriverEntry = &DriverNode->ListEntry;
  798. if (DriverEntry->FilePath.Buffer[0] != L'\\') {
  799. //
  800. // This is a relative pathname, so generate the full pathname
  801. // relative to the boot partition.
  802. //
  803. sprintf(DriverPath, "%wZ", &DriverEntry->FilePath);
  804. AbsolutePath = FALSE;
  805. } else if (memcmp(DriverEntry->FilePath.Buffer,
  806. SystemRootBuffer,
  807. (SystemRootLength * sizeof(WCHAR))) == 0) {
  808. //
  809. // This is a pathname starting with "\SystemRoot\", so just ignore
  810. // that part and treat like the previous case.
  811. //
  812. FileName.Buffer = DriverEntry->FilePath.Buffer + SystemRootLength;
  813. FileName.Length = (USHORT)(DriverEntry->FilePath.Length - (SystemRootLength * sizeof(WCHAR)));
  814. sprintf(DriverPath, "%wZ", &FileName);
  815. AbsolutePath = FALSE;
  816. } else {
  817. //
  818. // This is an absolute pathname, of the form
  819. // "\ArcDeviceName\dir\subdir\filename"
  820. //
  821. // We need to open the specified ARC device and pass that
  822. // to BlLoadDeviceDriver.
  823. //
  824. p = DeviceName.Buffer = DriverEntry->FilePath.Buffer+1;
  825. DeviceName.Length = 0;
  826. DeviceName.MaximumLength = DriverEntry->FilePath.MaximumLength-sizeof(WCHAR);
  827. while ((*p != L'\\') &&
  828. (DeviceName.Length < DeviceName.MaximumLength)) {
  829. ++p;
  830. DeviceName.Length += sizeof(WCHAR);
  831. }
  832. DeviceName.MaximumLength = DeviceName.Length;
  833. sprintf(DriverDevice, "%wZ", &DeviceName);
  834. Status = ArcOpen(DriverDevice,ArcOpenReadOnly,&DeviceId);
  835. FileName.Buffer = p+1;
  836. FileName.Length = DriverEntry->FilePath.Length - DeviceName.Length - 2*sizeof(WCHAR);
  837. FileName.MaximumLength = FileName.Length;
  838. //
  839. // Device successfully opened, parse out the path and filename.
  840. //
  841. sprintf(DriverPath, "%wZ", &FileName);
  842. AbsolutePath = TRUE;
  843. }
  844. //
  845. // Parse out the driver name from the driver path
  846. //
  847. NameStart = strrchr(DriverPath, '\\');
  848. if (NameStart != NULL) {
  849. strncpy(DriverName, NameStart+1, MAX_DRIVER_NAME_LENGTH - 1);
  850. DriverName[MAX_DRIVER_NAME_LENGTH - 1] = '\0';
  851. *NameStart = '\0';
  852. } else if (DriverPath[0]) {
  853. strncpy(DriverName, DriverPath, MAX_DRIVER_NAME_LENGTH - 1);
  854. DriverName[MAX_DRIVER_NAME_LENGTH - 1] = '\0';
  855. *DriverPath = '\0';
  856. } else {
  857. NextEntry = DriverEntry->Link.Flink;
  858. continue;
  859. }
  860. //
  861. // Ensure DriverPath is terminated with a '\\' if it's filled out.
  862. //
  863. if (DriverPath[0]) {
  864. strcat(DriverPath, "\\");
  865. }
  866. if (AbsolutePath) {
  867. //
  868. // There is only one entry if an absolute path is specified (in
  869. // this case we cannot do last known good).
  870. //
  871. PathSource = &LocalPathSet.Source[0];
  872. PathSource->DeviceId = DeviceId;
  873. PathSource->DeviceName = DriverDevice;
  874. PathSource->DirectoryPath = "\\";
  875. LocalPathSet.PathCount = 1;
  876. LocalPathSet.AliasName = NULL;
  877. strcpy(LocalPathSet.PathOffset, DriverPath);
  878. } else {
  879. //
  880. // It's relative. Copy over the DefaultPathSet array so we can
  881. // edit our own local copy.
  882. //
  883. *((PSPARSE_PATH_SET) &LocalPathSet) = *((PSPARSE_PATH_SET) DefaultPathSet);
  884. for(Index=0; Index < DefaultPathSet->PathCount; Index++) {
  885. LocalPathSet.Source[Index] = DefaultPathSet->Source[Index];
  886. }
  887. //
  888. // Now append our relative path to the PathOffset already present
  889. // in our local copy.
  890. //
  891. strcat(LocalPathSet.PathOffset, DriverPath);
  892. }
  893. if (Status == ESUCCESS) {
  894. Status = BlLoadDeviceDriver(&LocalPathSet,
  895. DriverName,
  896. NULL,
  897. LDRP_ENTRY_PROCESSED,
  898. &DriverEntry->LdrEntry);
  899. }
  900. NextEntry = DriverEntry->Link.Flink;
  901. if (Status != ESUCCESS) {
  902. //
  903. // Attempt to load driver failed, remove it from the list.
  904. //
  905. RemoveEntryList(&DriverEntry->Link);
  906. //
  907. // Check the Error Control of the failed driver. If it
  908. // was critical, fail the boot. If the driver
  909. // wasn't critical, keep going.
  910. //
  911. if (DriverNode->ErrorControl == CriticalError) {
  912. strcpy(BadFileName, DriverPath);
  913. strcat(BadFileName, DriverName);
  914. return(Status);
  915. }
  916. }
  917. }
  918. return(ESUCCESS);
  919. }
  920. BOOLEAN
  921. BlRecoverHive(
  922. PVOID RegistryBase,
  923. ULONG_PTR LogBase
  924. )
  925. /*++
  926. Routine Description:
  927. Applies log from LogBase over the RegistryBase
  928. Arguments:
  929. Return Value:
  930. ESUCCESS is returned if the system hive was successfully loaded.
  931. Otherwise, an unsuccessful status is returned.
  932. --*/
  933. {
  934. PHBASE_BLOCK BaseBlockHive;
  935. PHBASE_BLOCK BaseBlockLog;
  936. ULONG FileOffset = HSECTOR_SIZE;
  937. ULONG DirtyVectorSignature = 0;
  938. PUCHAR FlatLog;
  939. PUCHAR FlatReg;
  940. ULONG VectorSize;
  941. ULONG Length;
  942. ULONG ClusterSize;
  943. ULONG HeaderLength;
  944. RTL_BITMAP BitMap;
  945. PULONG Vector;
  946. ULONG Current;
  947. ULONG Start;
  948. ULONG End;
  949. PUCHAR MemoryBlock;
  950. PUCHAR Dest;
  951. ULONG i;
  952. BaseBlockHive = (PHBASE_BLOCK)RegistryBase;
  953. BaseBlockLog = (PHBASE_BLOCK)LogBase;
  954. FlatLog = (PUCHAR)LogBase;
  955. FlatReg = (PUCHAR)RegistryBase;
  956. ClusterSize = BaseBlockLog->Cluster * HSECTOR_SIZE;
  957. HeaderLength = ROUND_UP(HLOG_HEADER_SIZE, ClusterSize);
  958. FileOffset = ClusterSize;
  959. FileOffset = ROUND_UP(FileOffset, HeaderLength);
  960. if(HvpHeaderCheckSum(BaseBlockHive) != BaseBlockHive->CheckSum ) {
  961. //
  962. // recover header case
  963. //
  964. RtlCopyMemory((PVOID)BaseBlockHive,(PVOID)BaseBlockLog,ClusterSize);
  965. BaseBlockHive->Type = HFILE_TYPE_PRIMARY;
  966. } else {
  967. //
  968. // if not recoverheader (which implies recoverdata)
  969. //
  970. ASSERT( BaseBlockHive->Sequence1 != BaseBlockHive->Sequence2 );
  971. }
  972. DirtyVectorSignature = *((PULONG)(FlatLog + FileOffset));
  973. FileOffset += sizeof(DirtyVectorSignature);
  974. if (DirtyVectorSignature != HLOG_DV_SIGNATURE) {
  975. return FALSE;
  976. }
  977. Length = BaseBlockHive->Length;
  978. VectorSize = Length / HSECTOR_SIZE;
  979. Vector = (PULONG)(FlatLog + FileOffset);
  980. RtlInitializeBitMap(&BitMap, Vector, VectorSize);
  981. FileOffset += VectorSize / 8;
  982. FileOffset = ROUND_UP(FileOffset, ClusterSize);
  983. //
  984. // step through the diry map, and copy from the log to the flat hive
  985. //
  986. Current = 0;
  987. while (Current < VectorSize) {
  988. //
  989. // find next contiguous block of entries to read in
  990. //
  991. for (i = Current; i < VectorSize; i++) {
  992. if (RtlCheckBit(&BitMap, i) == 1) {
  993. break;
  994. }
  995. }
  996. Start = i;
  997. for ( ; i < VectorSize; i++) {
  998. if (RtlCheckBit(&BitMap, i) == 0) {
  999. break;
  1000. }
  1001. }
  1002. End = i;
  1003. Current = End;
  1004. //
  1005. // Start == number of 1st sector, End == number of Last sector + 1
  1006. //
  1007. Length = (End - Start) * HSECTOR_SIZE;
  1008. if( 0 == Length ) {
  1009. // no more dirty blocks.
  1010. break;
  1011. }
  1012. MemoryBlock = (PUCHAR)(FlatLog + FileOffset);
  1013. FileOffset += Length;
  1014. ASSERT((FileOffset % ClusterSize) == 0);
  1015. Dest = (PUCHAR)(FlatReg + HBLOCK_SIZE + Start * HSECTOR_SIZE);
  1016. //
  1017. // copy recovered data in the right locations inside the flat hive image
  1018. //
  1019. RtlCopyMemory(Dest,MemoryBlock, Length);
  1020. }
  1021. BaseBlockHive->Sequence2 = BaseBlockHive->Sequence1;
  1022. BaseBlockHive->CheckSum = HvpHeaderCheckSum(BaseBlockHive);
  1023. return TRUE;
  1024. }
  1025. ARC_STATUS
  1026. BlLoadAndInitSystemHive(
  1027. IN ULONG DeviceId,
  1028. IN PCHAR DeviceName,
  1029. IN PCHAR DirectoryPath,
  1030. IN PCHAR HiveName,
  1031. IN BOOLEAN IsAlternate,
  1032. OUT PBOOLEAN RestartSetup,
  1033. OUT PBOOLEAN LogPresent
  1034. )
  1035. /*++
  1036. Routine Description:
  1037. Loads the registry SYSTEM hive, verifies it is a valid hive file,
  1038. and inits the relevant registry structures. (particularly the HHIVE)
  1039. Arguments:
  1040. DeviceId - Supplies the file id of the device the system tree is on.
  1041. DeviceName - Supplies the name of the device the system tree is on.
  1042. DirectoryPath - Supplies a pointer to the zero-terminated directory path
  1043. of the root of the NT tree.
  1044. HiveName - Supplies the name of the system hive (ie, "SYSTEM",
  1045. "SYSTEM.ALT", or "SYSTEM.SAV").
  1046. IsAlternate - Supplies whether or not the hive to be loaded is the
  1047. alternate hive.
  1048. RestartSetup - if the hive to be loaded is not the alternate, then
  1049. this routine will check for a value of RestartSetup in the Setup
  1050. key. If present and non-0, then this variable receives TRUE.
  1051. Otherwise it receives FALSE.
  1052. Return Value:
  1053. ESUCCESS is returned if the system hive was successfully loaded.
  1054. Otherwise, an unsuccessful status is returned.
  1055. --*/
  1056. {
  1057. ARC_STATUS Status;
  1058. ULONG_PTR LogData;
  1059. *RestartSetup = FALSE;
  1060. *LogPresent = FALSE;
  1061. BlClearToEndOfLine();
  1062. Status = BlLoadSystemHive(DeviceId,
  1063. DeviceName,
  1064. DirectoryPath,
  1065. HiveName);
  1066. if (Status!=ESUCCESS) {
  1067. return(Status);
  1068. }
  1069. if (!BlInitializeHive(BlLoaderBlock->RegistryBase,
  1070. &BootHive,
  1071. IsAlternate)) {
  1072. if( !IsAlternate ) {
  1073. //
  1074. // try to recover the hive
  1075. //
  1076. Status = BlLoadSystemHiveLog(DeviceId,
  1077. DeviceName,
  1078. DirectoryPath,
  1079. "system.log",
  1080. &LogData );
  1081. if (Status!=ESUCCESS) {
  1082. return(Status);
  1083. }
  1084. *LogPresent = TRUE;
  1085. if( !BlRecoverHive( BlLoaderBlock->RegistryBase,
  1086. LogData ) ) {
  1087. BlFreeDescriptor( (ULONG)((ULONG_PTR)LogData & (~KSEG0_BASE)) >> PAGE_SHIFT );
  1088. return(EINVAL);
  1089. }
  1090. BlFreeDescriptor( (ULONG)((ULONG_PTR)LogData & (~KSEG0_BASE)) >> PAGE_SHIFT );
  1091. //
  1092. // we successfully recovered. Try setting up the hive again
  1093. //
  1094. if (!BlInitializeHive(BlLoaderBlock->RegistryBase,
  1095. &BootHive,
  1096. IsAlternate)) {
  1097. return(EINVAL);
  1098. }
  1099. //
  1100. // mark the hive as "recovered"
  1101. //
  1102. BootHive.Hive.BaseBlock->BootRecover = 1;
  1103. } else {
  1104. return(EINVAL);
  1105. }
  1106. } else {
  1107. //
  1108. // mark the hive as "no-recovered"
  1109. //
  1110. BootHive.Hive.BaseBlock->BootRecover = 0;
  1111. }
  1112. //
  1113. // See whether we need to switch to the backup setup hive.
  1114. //
  1115. *RestartSetup = BlpCheckRestartSetup();
  1116. return(ESUCCESS);
  1117. }
  1118. HCELL_INDEX
  1119. BlpDetermineControlSet(
  1120. IN OUT BOOLEAN *LastKnownGoodBoot
  1121. )
  1122. /*++
  1123. Routine Description:
  1124. Determines the appropriate control set and static hardware profile.
  1125. This routine ends the configuration prompt. If the user has hit a
  1126. key, the configuration menu is displayed. If the user has not hit
  1127. a key, but the default controlset specifies a non-zero timeout for
  1128. the configuration menu, the configuration menu is displayed.
  1129. If the configuration menu is displayed, further modifications to the
  1130. control set and hardware profile can be made by the user. If not,
  1131. the default hardware profile is selected.
  1132. Arguments:
  1133. LastKnownGoodBoot - On input, LastKnownGood indicates whether LKG has been
  1134. selected. This value is updated to TRUE if the user
  1135. chooses LKG via the profile configuration menu.
  1136. Return Value:
  1137. On success, HCELL_INDEX is control the set to boot from.
  1138. On error, HCELL_NIL is returned and LastKnownGoodBoot is unchanged.
  1139. --*/
  1140. {
  1141. BOOLEAN UseLastKnownGood;
  1142. BOOLEAN ConfigMenu = FALSE;
  1143. HCELL_INDEX ControlSet;
  1144. HCELL_INDEX ProfileControl;
  1145. UNICODE_STRING DefaultControlName;
  1146. UNICODE_STRING LkgControlName;
  1147. PUNICODE_STRING ControlName;
  1148. BOOLEAN AutoSelect;
  1149. ULONG ProfileTimeout = (ULONG)0;
  1150. PCM_HARDWARE_PROFILE_LIST ProfileList;
  1151. PCM_HARDWARE_PROFILE_ALIAS_LIST AliasList;
  1152. PCM_HARDWARE_PROFILE SelectedProfile;
  1153. DOCKING_STATION_INFO dockInfo = { 0, 0, 0, FW_DOCKINFO_DOCK_STATE_UNKNOWN };
  1154. PCONFIGURATION_COMPONENT_DATA dockInfoData;
  1155. ULONG flags;
  1156. #if DOCKINFO_VERBOSE
  1157. _TUCHAR Buffer[1024];
  1158. ULONG count;
  1159. USHORT dkState;
  1160. PTCHAR stateTxt;
  1161. #endif
  1162. //
  1163. // Preinit for failure
  1164. //
  1165. RtlInitUnicodeString(&DefaultControlName, L"Default");
  1166. RtlInitUnicodeString(&LkgControlName, L"LastKnownGood");
  1167. UseLastKnownGood = (*LastKnownGoodBoot);
  1168. if (ForceLastKnownGood) {
  1169. //
  1170. // last known good was selected from the
  1171. // advanced boot menu.
  1172. // this code path is entered when the user
  1173. // enters the advanced boot menu via the
  1174. // main boot menu.
  1175. //
  1176. UseLastKnownGood = TRUE;
  1177. }
  1178. if( !CmpValidateSelect(&BootHive.Hive,
  1179. BootHive.Hive.BaseBlock->RootCell) ) {
  1180. //
  1181. // some of the essential values (Current,Default,Failed,LastKnownGood)
  1182. // does not exist under \SYSTEM\Select key
  1183. //
  1184. return HCELL_NIL;
  1185. }
  1186. do_it_again:
  1187. //
  1188. // Get the appropriate control set
  1189. // and check the hardware profile timeout value.
  1190. //
  1191. if (UseLastKnownGood) {
  1192. ControlName = &LkgControlName;
  1193. } else {
  1194. ControlName = &DefaultControlName;
  1195. }
  1196. ControlSet = CmpFindControlSet(&BootHive.Hive,
  1197. BootHive.Hive.BaseBlock->RootCell,
  1198. ControlName,
  1199. &AutoSelect);
  1200. if (ControlSet == HCELL_NIL) {
  1201. return(HCELL_NIL);
  1202. }
  1203. //
  1204. // Check the hardware profile configuration options to
  1205. // determine the timeout value for the config menu.
  1206. //
  1207. ProfileList = NULL;
  1208. AliasList = NULL;
  1209. ProfileControl = CmpFindProfileOption(&BootHive.Hive,
  1210. ControlSet,
  1211. &ProfileList,
  1212. &AliasList,
  1213. &ProfileTimeout);
  1214. //
  1215. // Pull the Docking information from the hardware tree.
  1216. //
  1217. dockInfoData = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  1218. PeripheralClass,
  1219. DockingInformation,
  1220. NULL);
  1221. if (NULL == dockInfoData) {
  1222. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  1223. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_UNKNOWN;
  1224. BlLoaderBlock->Extension->Profile.Capabilities = 0;
  1225. BlLoaderBlock->Extension->Profile.DockID = 0;
  1226. BlLoaderBlock->Extension->Profile.SerialNumber = 0;
  1227. } else if (sizeof (dockInfo) <=
  1228. dockInfoData->ComponentEntry.ConfigurationDataLength) {
  1229. RtlCopyMemory (
  1230. &dockInfo,
  1231. (PUCHAR) (dockInfoData->ConfigurationData) + sizeof(CM_PARTIAL_RESOURCE_LIST),
  1232. sizeof (dockInfo));
  1233. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_FAILURE;
  1234. switch (dockInfo.ReturnCode) {
  1235. case FW_DOCKINFO_SUCCESS:
  1236. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  1237. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_DOCKED;
  1238. BlLoaderBlock->Extension->Profile.Capabilities = dockInfo.Capabilities;
  1239. BlLoaderBlock->Extension->Profile.DockID = dockInfo.DockID;
  1240. BlLoaderBlock->Extension->Profile.SerialNumber = dockInfo.SerialNumber;
  1241. break;
  1242. case FW_DOCKINFO_SYSTEM_NOT_DOCKED:
  1243. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  1244. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_UNDOCKED;
  1245. BlLoaderBlock->Extension->Profile.Capabilities = dockInfo.Capabilities;
  1246. BlLoaderBlock->Extension->Profile.DockID = dockInfo.DockID;
  1247. BlLoaderBlock->Extension->Profile.SerialNumber = dockInfo.SerialNumber;
  1248. break;
  1249. case FW_DOCKINFO_DOCK_STATE_UNKNOWN:
  1250. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  1251. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_UNKNOWN;
  1252. BlLoaderBlock->Extension->Profile.Capabilities = dockInfo.Capabilities;
  1253. BlLoaderBlock->Extension->Profile.DockID = dockInfo.DockID;
  1254. BlLoaderBlock->Extension->Profile.SerialNumber = dockInfo.SerialNumber;
  1255. break;
  1256. case FW_DOCKINFO_FUNCTION_NOT_SUPPORTED:
  1257. case FW_DOCKINFO_BIOS_NOT_CALLED:
  1258. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  1259. default:
  1260. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_UNSUPPORTED;
  1261. BlLoaderBlock->Extension->Profile.Capabilities = dockInfo.Capabilities;
  1262. BlLoaderBlock->Extension->Profile.DockID = dockInfo.DockID;
  1263. BlLoaderBlock->Extension->Profile.SerialNumber = dockInfo.SerialNumber;
  1264. break;
  1265. }
  1266. } else {
  1267. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  1268. BlLoaderBlock->Extension->Profile.Capabilities = 0;
  1269. BlLoaderBlock->Extension->Profile.DockID = 0;
  1270. BlLoaderBlock->Extension->Profile.SerialNumber = 0;
  1271. }
  1272. #ifdef DOCKINFO_VERBOSE
  1273. dkState = BlLoaderBlock->Extension->Profile.DockingState;
  1274. if ((dkState & HW_PROFILE_DOCKSTATE_UNKNOWN) == HW_PROFILE_DOCKSTATE_UNKNOWN) {
  1275. stateTxt = TEXT("Unknown");
  1276. } else if (dkState & HW_PROFILE_DOCKSTATE_DOCKED) {
  1277. stateTxt = TEXT("Docked");
  1278. } else if (dkState & HW_PROFILE_DOCKSTATE_UNDOCKED) {
  1279. stateTxt = TEXT("Undocked");
  1280. } else {
  1281. stateTxt = TEXT("Truely unknown");
  1282. }
  1283. _stprintf(Buffer,
  1284. TEXT("Profile Docking: <%x, %s> := %x [%x, %x] \r\n\0"),
  1285. BlLoaderBlock->Extension->Profile.Status,
  1286. stateTxt,
  1287. BlLoaderBlock->Extension->Profile.Capabilities,
  1288. BlLoaderBlock->Extension->Profile.DockID,
  1289. BlLoaderBlock->Extension->Profile.SerialNumber);
  1290. ArcWrite(BlConsoleOutDeviceId, Buffer, _tcslen(Buffer)*sizeof(TCHAR), &count);
  1291. _stprintf(Buffer, TEXT("press 'y' (lowercase) to continue...\r\n\0"));
  1292. ArcWrite(BlConsoleOutDeviceId, Buffer, _tcslen(Buffer)*sizeof(TCHAR), &count);
  1293. #ifdef EFI
  1294. //
  1295. // disable efi watchdog when waiting for user input
  1296. //
  1297. DisableEFIWatchDog();
  1298. #endif
  1299. while (BlGetKey() != 'y') {
  1300. //
  1301. // Nothing
  1302. //
  1303. }
  1304. #ifdef EFI
  1305. //
  1306. // reset EFI watchdog
  1307. //
  1308. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  1309. #endif
  1310. #endif
  1311. //
  1312. // Filter the list of Hardware Profiles to
  1313. // eliminate profiles that should not be considered
  1314. //
  1315. if (NULL != ProfileList) {
  1316. if (ProfileList->CurrentProfileCount > 0) {
  1317. BlDockInfoFilterProfileList (ProfileList, AliasList);
  1318. }
  1319. }
  1320. //
  1321. // Now check to see whether the config menu should be displayed.
  1322. // Display the menu if:
  1323. // - user has pressed a key OR
  1324. // - we are booting from LKG and AutoSelect is FALSE. OR
  1325. // - ProfileTimeout != 0
  1326. //
  1327. if (!BlEndConfigPrompt()) {
  1328. if (!UseLastKnownGood && ForceLastKnownGood) {
  1329. //
  1330. // last known good was selected from the
  1331. // advanced boot menu.
  1332. // this code path is entered when the user
  1333. // enters the advanced boot menu by pressing
  1334. // F8 while the cinfiguration hives are preparing to load.
  1335. //
  1336. // the currentcontrolset has already been set to the
  1337. // "default" control set, so go back and try this again to
  1338. // load the "lastknowngood" controlset.
  1339. //
  1340. UseLastKnownGood = TRUE;
  1341. goto do_it_again;
  1342. }
  1343. ConfigMenu = FALSE;
  1344. } else {
  1345. ConfigMenu = TRUE;
  1346. }
  1347. if (ConfigMenu || ForceLastKnownGood ||
  1348. (UseLastKnownGood && !AutoSelect) ||
  1349. ((ProfileTimeout != 0) &&
  1350. (ProfileList != NULL) &&
  1351. (ProfileList->CurrentProfileCount > 1))) {
  1352. //
  1353. // Display the configuration menu.
  1354. //
  1355. BlRebootSystem = !BlConfigMenuPrompt(ProfileTimeout,
  1356. &UseLastKnownGood,
  1357. &ControlSet,
  1358. &ProfileList,
  1359. &AliasList,
  1360. &SelectedProfile);
  1361. if (BlRebootSystem) {
  1362. ArcReboot();
  1363. }
  1364. BlClearScreen();
  1365. } else {
  1366. if ((ProfileControl != HCELL_NIL) &&
  1367. (ProfileList != NULL)) {
  1368. //
  1369. // The system is configured to boot the default
  1370. // profile directly. Since the returned profile
  1371. // list is sorted by priority, the first entry in
  1372. // the list is our default.
  1373. //
  1374. if (HW_PROFILE_STATUS_SUCCESS ==
  1375. BlLoaderBlock->Extension->Profile.Status) {
  1376. flags = (ProfileList->Profile[0].Flags);
  1377. if (flags & CM_HP_FLAGS_PRISTINE) {
  1378. BlLoaderBlock->Extension->Profile.Status =
  1379. HW_PROFILE_STATUS_PRISTINE_MATCH;
  1380. } else if (flags & CM_HP_FLAGS_TRUE_MATCH) {
  1381. BlLoaderBlock->Extension->Profile.Status =
  1382. HW_PROFILE_STATUS_TRUE_MATCH;
  1383. } else if (flags & CM_HP_FLAGS_ALIASABLE) {
  1384. BlLoaderBlock->Extension->Profile.Status =
  1385. HW_PROFILE_STATUS_ALIAS_MATCH;
  1386. }
  1387. }
  1388. CmpSetCurrentProfile(&BootHive.Hive,
  1389. ControlSet,
  1390. &ProfileList->Profile[0]);
  1391. }
  1392. }
  1393. //
  1394. // Update the passed in parameter. We should only be doing this if we have
  1395. // something real to return.
  1396. //
  1397. //ASSERT(ControlSet != HCELL_NIL);
  1398. *LastKnownGoodBoot = UseLastKnownGood;
  1399. return(ControlSet);
  1400. }
  1401. BOOLEAN
  1402. BlpCheckRestartSetup(
  1403. VOID
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. Examine the system hive loaded and described by BootHive, to see
  1408. whether it contains a Setup key, and if so, whether that key has
  1409. a "RestartSetup" value that is non-0.
  1410. Arguments:
  1411. None.
  1412. Return Value:
  1413. Boolean value indicating whether the above condition is satisfied.
  1414. --*/
  1415. {
  1416. HCELL_INDEX KeyCell;
  1417. HCELL_INDEX ValueCell;
  1418. UNICODE_STRING UnicodeString;
  1419. PCM_KEY_VALUE Value;
  1420. PULONG Data;
  1421. ULONG DataSize;
  1422. //
  1423. // Address the Setup key
  1424. //
  1425. RtlInitUnicodeString(&UnicodeString,L"Setup");
  1426. KeyCell = CmpFindSubKeyByName(
  1427. &BootHive.Hive,
  1428. (PCM_KEY_NODE)HvGetCell(&BootHive.Hive,BootHive.Hive.BaseBlock->RootCell),
  1429. &UnicodeString
  1430. );
  1431. if(KeyCell == HCELL_NIL) {
  1432. return(FALSE);
  1433. }
  1434. //
  1435. // Find RestartSetup value in Setup key
  1436. //
  1437. RtlInitUnicodeString(&UnicodeString,L"RestartSetup");
  1438. ValueCell = CmpFindValueByName(
  1439. &BootHive.Hive,
  1440. (PCM_KEY_NODE)HvGetCell(&BootHive.Hive,KeyCell),
  1441. &UnicodeString
  1442. );
  1443. if(ValueCell == HCELL_NIL) {
  1444. return(FALSE);
  1445. }
  1446. //
  1447. // Validate value and check.
  1448. //
  1449. Value = (PCM_KEY_VALUE)HvGetCell(&BootHive.Hive,ValueCell);
  1450. if(Value->Type != REG_DWORD) {
  1451. return(FALSE);
  1452. }
  1453. Data = (PULONG)(CmpIsHKeyValueSmall(DataSize,Value->DataLength)
  1454. ? (struct _CELL_DATA *)&Value->Data
  1455. : HvGetCell(&BootHive.Hive,Value->Data));
  1456. if(DataSize != sizeof(ULONG)) {
  1457. return(FALSE);
  1458. }
  1459. return((BOOLEAN)(*Data != 0));
  1460. }
  1461. #if defined(REMOTE_BOOT)
  1462. BOOLEAN
  1463. BlpQueryRemoteBootParameter(
  1464. IN HCELL_INDEX ControlSet,
  1465. IN PWSTR ValueName,
  1466. IN ULONG ValueType,
  1467. OUT PVOID ValueBuffer,
  1468. IN ULONG ValueBufferLength
  1469. )
  1470. /*++
  1471. Routine Description:
  1472. Query a parameter from under Control\RemoteBoot.
  1473. Arguments:
  1474. ControlSet - The index of the current control set.
  1475. ValueName - The name of the value to query.
  1476. ValueType - The expected type of the value.
  1477. ValueBuffer - The location to return the data.
  1478. ValueBufferLength - The length of the buffer.
  1479. Return Value:
  1480. Boolean value indicating whether the data was read successfully.
  1481. --*/
  1482. {
  1483. UNICODE_STRING Name;
  1484. HCELL_INDEX Control;
  1485. HCELL_INDEX RemoteBoot;
  1486. HCELL_INDEX ValueCell;
  1487. PCM_KEY_VALUE Value;
  1488. ULONG RealSize;
  1489. BOOLEAN ValueSmall;
  1490. //
  1491. // Find Services node
  1492. //
  1493. RtlInitUnicodeString(&Name, L"Control");
  1494. Control = CmpFindSubKeyByName(
  1495. &BootHive.Hive,
  1496. (PCM_KEY_NODE)HvGetCell(&BootHive.Hive,ControlSet),
  1497. &Name);
  1498. if (Control == HCELL_NIL) {
  1499. return(FALSE);
  1500. }
  1501. //
  1502. // Find RemoteBoot node
  1503. //
  1504. RtlInitUnicodeString(&Name, L"RemoteBoot");
  1505. RemoteBoot = CmpFindSubKeyByName(
  1506. &BootHive.Hive,
  1507. (PCM_KEY_NODE)HvGetCell(&BootHive.Hive,Control),
  1508. &Name);
  1509. if (RemoteBoot == HCELL_NIL) {
  1510. return(FALSE);
  1511. }
  1512. //
  1513. // Find value
  1514. //
  1515. RtlInitUnicodeString(&Name, ValueName);
  1516. ValueCell = CmpFindValueByName(
  1517. &BootHive.Hive,
  1518. (PCM_KEY_NODE)HvGetCell(&BootHive.Hive,RemoteBoot),
  1519. &Name);
  1520. if (ValueCell == HCELL_NIL) {
  1521. return(FALSE);
  1522. }
  1523. Value = (PCM_KEY_VALUE)HvGetCell(&BootHive.Hive, ValueCell);
  1524. if (Value->Type != ValueType) {
  1525. return(FALSE);
  1526. }
  1527. //
  1528. // This determines if the value is small (stored right in Value)
  1529. // or not, and also returns the real size of it.
  1530. //
  1531. ValueSmall = CmpIsHKeyValueSmall(RealSize,Value->DataLength);
  1532. if (RealSize > ValueBufferLength) {
  1533. return(FALSE);
  1534. }
  1535. RtlMoveMemory(
  1536. ValueBuffer,
  1537. (ValueSmall ?
  1538. (struct _CELL_DATA *)&Value->Data :
  1539. HvGetCell(&BootHive.Hive,Value->Data)),
  1540. RealSize);
  1541. return(TRUE);
  1542. }
  1543. #endif // defined(REMOTE_BOOT)
  1544. PTCHAR
  1545. BlScanRegistry(
  1546. IN PWSTR BootFileSystemPath,
  1547. IN OUT BOOLEAN *LastKnownGoodBoot,
  1548. OUT PLIST_ENTRY BootDriverListHead,
  1549. OUT PUNICODE_STRING AnsiCodepage,
  1550. OUT PUNICODE_STRING OemCodepage,
  1551. OUT PUNICODE_STRING LanguageTable,
  1552. OUT PUNICODE_STRING OemHalFont,
  1553. #ifdef _WANT_MACHINE_IDENTIFICATION
  1554. OUT PUNICODE_STRING Biosinfo,
  1555. #endif
  1556. OUT PSETUP_LOADER_BLOCK SetupLoaderBlock,
  1557. OUT BOOLEAN *ServerHive
  1558. )
  1559. /*++
  1560. Routine Description:
  1561. Scans the SYSTEM hive, determines the control set and static hardware
  1562. profile (with appropriate input from the user) and finally
  1563. computes the list of boot drivers to be loaded.
  1564. Arguments:
  1565. BootFileSystemPath - Supplies the name of the image the filesystem
  1566. for the boot volume was read from. The last entry in
  1567. BootDriverListHead will refer to this file, and to the registry
  1568. key entry that controls it.
  1569. LastKnownGoodBoot - On input, LastKnownGood indicates whether LKG has been
  1570. selected. This value is updated to TRUE if the user
  1571. chooses LKG via the profile configuration menu.
  1572. BootDriverListHead - Receives a pointer to the first element of the
  1573. list of boot drivers. Each element in this singly linked list will
  1574. provide the loader with two paths. The first is the path of the
  1575. file that contains the driver to load, the second is the path of
  1576. the registry key that controls that driver. Both will be passed
  1577. to the system via the loader heap.
  1578. AnsiCodepage - Receives the name of the ANSI codepage data file
  1579. OemCodepage - Receives the name of the OEM codepage data file
  1580. Language - Receives the name of the language case table data file
  1581. OemHalfont - receives the name of the OEM font to be used by the HAL.
  1582. SetupLoaderBlock - if non-NULL, used to return information about the
  1583. net boot card.
  1584. ServerHive - Returns TRUE if this is a server hive, else FALSE.
  1585. Return Value:
  1586. NULL if all is well.
  1587. NON-NULL if the hive is corrupt or inconsistent. Return value is a
  1588. pointer to a string that describes what is wrong. On error LastKnownGood
  1589. is unchanged.
  1590. --*/
  1591. {
  1592. HCELL_INDEX ControlSet;
  1593. UNICODE_STRING TmpName;
  1594. HCELL_INDEX Control;
  1595. HCELL_INDEX ProductOptions;
  1596. HCELL_INDEX ValueCell;
  1597. PCM_KEY_VALUE Value;
  1598. ULONG RealSize;
  1599. PWCHAR CellString;
  1600. BOOLEAN UsingLastKnownGood;
  1601. #ifdef _WANT_MACHINE_IDENTIFICATION
  1602. UNICODE_STRING regDate;
  1603. CHAR date[9];
  1604. ANSI_STRING ansiString;
  1605. UNICODE_STRING biosDate;
  1606. WCHAR buffer[9];
  1607. BOOLEAN biosDateChanged;
  1608. #endif
  1609. #if !defined(REMOTE_BOOT)
  1610. UNREFERENCED_PARAMETER(SetupLoaderBlock);
  1611. #endif
  1612. //
  1613. // Preinit.
  1614. //
  1615. UsingLastKnownGood = *LastKnownGoodBoot;
  1616. //
  1617. // Get the appropriate control set.
  1618. //
  1619. ControlSet = BlpDetermineControlSet(&UsingLastKnownGood);
  1620. if (ControlSet == HCELL_NIL) {
  1621. return(TEXT("CmpFindControlSet"));
  1622. }
  1623. if (!CmpFindNLSData(&BootHive.Hive,
  1624. ControlSet,
  1625. AnsiCodepage,
  1626. OemCodepage,
  1627. LanguageTable,
  1628. OemHalFont)) {
  1629. return(TEXT("CmpFindNLSData"));
  1630. }
  1631. InitializeListHead(BootDriverListHead);
  1632. if (!CmpFindDrivers(&BootHive.Hive,
  1633. ControlSet,
  1634. BootLoad,
  1635. BootFileSystemPath,
  1636. BootDriverListHead)) {
  1637. return(TEXT("CmpFindDriver"));
  1638. }
  1639. if (!CmpSortDriverList(&BootHive.Hive,
  1640. ControlSet,
  1641. BootDriverListHead)) {
  1642. return(TEXT("Missing or invalid Control\\ServiceGroupOrder\\List registry value"));
  1643. }
  1644. if (!CmpResolveDriverDependencies(BootDriverListHead)) {
  1645. return(TEXT("CmpResolveDriverDependencies"));
  1646. }
  1647. if (ServerHive != NULL) {
  1648. *ServerHive = FALSE;
  1649. //
  1650. // Find Control node
  1651. //
  1652. RtlInitUnicodeString(&TmpName, L"Control");
  1653. Control = CmpFindSubKeyByName(&BootHive.Hive,
  1654. (PCM_KEY_NODE)HvGetCell(&BootHive.Hive, ControlSet),
  1655. &TmpName
  1656. );
  1657. if (Control == HCELL_NIL) {
  1658. return(TEXT("Missing Control key"));
  1659. }
  1660. //
  1661. // Find ProductOptions node
  1662. //
  1663. RtlInitUnicodeString(&TmpName, L"ProductOptions");
  1664. ProductOptions = CmpFindSubKeyByName(&BootHive.Hive,
  1665. (PCM_KEY_NODE)HvGetCell(&BootHive.Hive,Control),
  1666. &TmpName
  1667. );
  1668. if (ProductOptions == HCELL_NIL) {
  1669. return(TEXT("Missing ProductOptions key"));
  1670. }
  1671. //
  1672. // Find value
  1673. //
  1674. RtlInitUnicodeString(&TmpName, L"ProductType");
  1675. ValueCell = CmpFindValueByName(&BootHive.Hive,
  1676. (PCM_KEY_NODE)HvGetCell(&BootHive.Hive, ProductOptions),
  1677. &TmpName
  1678. );
  1679. if (ValueCell == HCELL_NIL) {
  1680. return(TEXT("Missing ProductType value"));
  1681. }
  1682. Value = (PCM_KEY_VALUE)HvGetCell(&BootHive.Hive, ValueCell);
  1683. if (Value->Type != REG_SZ) {
  1684. return(TEXT("Bad ProductType value"));
  1685. }
  1686. //
  1687. // This determines if the value is small (stored right in Value)
  1688. // or not, and also returns the real size of it.
  1689. //
  1690. CellString = (PWCHAR)(CmpIsHKeyValueSmall(RealSize, Value->DataLength) ?
  1691. (struct _CELL_DATA *)&Value->Data :
  1692. HvGetCell(&BootHive.Hive, Value->Data)
  1693. );
  1694. //
  1695. // Now compare if this is a server hive or not.
  1696. // The proper way to check this is to check the string against
  1697. // the "professional" type 'WinNT'. If it's not professional,
  1698. // it must be a server. (There are multiple strings for different
  1699. // server flavours.)
  1700. //
  1701. *ServerHive = (BOOLEAN)(_wcsicmp(L"WinNT", CellString) != 0);
  1702. }
  1703. #if defined(REMOTE_BOOT)
  1704. if (SetupLoaderBlock != NULL) {
  1705. ULONG EnableIpSecurity;
  1706. if (BlpQueryRemoteBootParameter(
  1707. ControlSet,
  1708. L"EnableIpSecurity",
  1709. REG_DWORD,
  1710. &EnableIpSecurity,
  1711. sizeof(EnableIpSecurity))) {
  1712. if (EnableIpSecurity != 0) {
  1713. SetupLoaderBlock->Flags |= SETUPBLK_FLAGS_IPSEC_ENABLED;
  1714. }
  1715. }
  1716. if (BlpQueryRemoteBootParameter(
  1717. ControlSet,
  1718. L"NetCardInfo",
  1719. REG_BINARY,
  1720. SetupLoaderBlock->NetbootCardInfo,
  1721. SetupLoaderBlock->NetbootCardInfoLength)) {
  1722. if (!BlpQueryRemoteBootParameter(
  1723. ControlSet,
  1724. L"HardwareId",
  1725. REG_SZ,
  1726. SetupLoaderBlock->NetbootCardHardwareId,
  1727. sizeof(SetupLoaderBlock->NetbootCardHardwareId))) {
  1728. SetupLoaderBlock->NetbootCardHardwareId[0] = L'\0';
  1729. }
  1730. if (!BlpQueryRemoteBootParameter(
  1731. ControlSet,
  1732. L"DriverName",
  1733. REG_SZ,
  1734. SetupLoaderBlock->NetbootCardDriverName,
  1735. sizeof(SetupLoaderBlock->NetbootCardDriverName))) {
  1736. SetupLoaderBlock->NetbootCardDriverName[0] = L'\0';
  1737. }
  1738. if (!BlpQueryRemoteBootParameter(
  1739. ControlSet,
  1740. L"ServiceName",
  1741. REG_SZ,
  1742. SetupLoaderBlock->NetbootCardServiceName,
  1743. sizeof(SetupLoaderBlock->NetbootCardServiceName))) {
  1744. SetupLoaderBlock->NetbootCardServiceName[0] = L'\0';
  1745. }
  1746. }
  1747. }
  1748. #endif // defined(REMOTE_BOOT)
  1749. #ifdef _WANT_MACHINE_IDENTIFICATION
  1750. biosDateChanged = TRUE;
  1751. if (CmpGetBiosDateFromRegistry(&BootHive.Hive, ControlSet, &regDate)) {
  1752. //
  1753. // Read the date from the BIOS ROM.
  1754. //
  1755. memcpy(date, (PVOID)0xffff5, 8);
  1756. date[8] = '\0';
  1757. //
  1758. // Convert the date into unicode string.
  1759. //
  1760. ansiString.Buffer = date;
  1761. ansiString.Length = (USHORT) strlen(date);
  1762. ansiString.MaximumLength = ansiString.Length + 1;
  1763. biosDate.Buffer = buffer;
  1764. biosDate.MaximumLength = (ansiString.Length << 1) + sizeof(UNICODE_NULL);
  1765. RtlAnsiStringToUnicodeString(&biosDate, &ansiString, FALSE);
  1766. //
  1767. // Check if the dates are different.
  1768. //
  1769. if (RtlCompareUnicodeString(&biosDate, &regDate, FALSE) == 0) {
  1770. biosDateChanged = FALSE;
  1771. }
  1772. }
  1773. Biosinfo->Length = 0;
  1774. if (biosDateChanged) {
  1775. CmpGetBiosinfoFileNameFromRegistry(&BootHive.Hive, ControlSet, Biosinfo);
  1776. }
  1777. #endif // defined(_WANT_MACHINE_IDENTIFICATION)
  1778. *LastKnownGoodBoot = UsingLastKnownGood;
  1779. return( NULL );
  1780. }
  1781. ARC_STATUS
  1782. BlAddToBootDriverList(
  1783. IN PLIST_ENTRY BootDriverListHead,
  1784. IN PWSTR DriverName,
  1785. IN PWSTR Name,
  1786. IN PWSTR Group,
  1787. IN ULONG Tag,
  1788. IN ULONG ErrorControl,
  1789. IN BOOLEAN InsertAtHead
  1790. )
  1791. /*++
  1792. Routine Description:
  1793. Adds a single driver to the boot driver list. The list
  1794. is NOT re-sorted.
  1795. Arguments:
  1796. BootDriverListHead - Receives a pointer to the first element of the
  1797. list of boot drivers. Each element in this singly linked list will
  1798. provide the loader with two paths. The first is the path of the
  1799. file that contains the driver to load, the second is the path of
  1800. the registry key that controls that driver. Both will be passed
  1801. to the system via the loader heap.
  1802. DriverName - The name of the driver. This will be stored with
  1803. \system32\drivers on the front.
  1804. Name - The service name of the driver. Typically will be DriverName
  1805. without the ".sys".
  1806. Group - The group this driver is in.
  1807. Tag - The tag value within the group for this driver.
  1808. ErrorControl - The error control value for this driver.
  1809. InsertAtHead - Should this driver be inserted at the head of the list, otw tail.
  1810. Return Value:
  1811. ESUCCESS if the driver is successfully inserted.
  1812. ENOMEM if there is an allocation failure.
  1813. --*/
  1814. {
  1815. PBOOT_DRIVER_NODE DriverNode;
  1816. PBOOT_DRIVER_LIST_ENTRY DriverListEntry;
  1817. USHORT Length;
  1818. DriverNode = BlpHiveAllocate(sizeof(BOOT_DRIVER_NODE),FALSE,0);
  1819. if (DriverNode == FALSE) {
  1820. return ENOMEM;
  1821. }
  1822. DriverListEntry = &DriverNode->ListEntry;
  1823. //
  1824. // FilePath
  1825. //
  1826. //
  1827. // when assigning the length, do some checking to make sure we don't
  1828. // overflow. if we do overflow, assign the length value to 0
  1829. // make sure we don't overflow (USHORT)-1
  1830. //
  1831. Length = RESET_SIZE_AT_USHORT_MAX(sizeof(L"System32\\Drivers\\") + (wcslen(DriverName) * sizeof(WCHAR)));
  1832. DriverListEntry->FilePath.Buffer = BlpHiveAllocate(Length,FALSE,0);
  1833. if (DriverListEntry->FilePath.Buffer == NULL) {
  1834. return ENOMEM;
  1835. }
  1836. DriverListEntry->FilePath.Length = 0;
  1837. DriverListEntry->FilePath.MaximumLength = Length;
  1838. RtlAppendUnicodeToString(&DriverListEntry->FilePath, L"System32\\Drivers\\");
  1839. RtlAppendUnicodeToString(&DriverListEntry->FilePath, DriverName);
  1840. //
  1841. // Registry Path
  1842. //
  1843. //
  1844. // when assigning the length, do some checking to make sure we don't
  1845. // overflow. if we do overflow, assign the length value to 0
  1846. // make sure we don't overflow (USHORT)-1
  1847. //
  1848. Length = RESET_SIZE_AT_USHORT_MAX(sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") +
  1849. (wcslen(Name) * sizeof(WCHAR)));
  1850. DriverListEntry->RegistryPath.Buffer = BlpHiveAllocate(Length,FALSE,0);
  1851. if (DriverListEntry->RegistryPath.Buffer == NULL) {
  1852. return ENOMEM;
  1853. }
  1854. DriverListEntry->RegistryPath.Length = 0;
  1855. DriverListEntry->RegistryPath.MaximumLength = Length;
  1856. RtlAppendUnicodeToString(&DriverListEntry->RegistryPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
  1857. RtlAppendUnicodeToString(&DriverListEntry->RegistryPath, Name);
  1858. //
  1859. // Group
  1860. //
  1861. //
  1862. // when assigning the length, do some checking to make sure we don't
  1863. // overflow. if we do overflow, assign the length value to 0
  1864. // make sure we don't overflow (USHORT)-1
  1865. //
  1866. Length = RESET_SIZE_AT_USHORT_MAX((wcslen(Group) + 1) * sizeof(WCHAR));
  1867. DriverNode->Group.Buffer = BlpHiveAllocate(Length,FALSE,0);
  1868. if (DriverNode->Group.Buffer == NULL) {
  1869. return ENOMEM;
  1870. }
  1871. DriverNode->Group.Length = 0;
  1872. DriverNode->Group.MaximumLength = Length;
  1873. RtlAppendUnicodeToString(&DriverNode->Group, Group);
  1874. //
  1875. // Name
  1876. //
  1877. //
  1878. // when assigning the length, do some checking to make sure we don't
  1879. // overflow. if we do overflow, assign the length value to 0
  1880. // make sure we don't overflow (USHORT)-1
  1881. //
  1882. Length = RESET_SIZE_AT_USHORT_MAX((wcslen(Name) + 1) * sizeof(WCHAR));
  1883. DriverNode->Name.Buffer = BlpHiveAllocate(Length,FALSE,0);
  1884. if (DriverNode->Name.Buffer == NULL) {
  1885. return ENOMEM;
  1886. }
  1887. DriverNode->Name.Length = 0;
  1888. DriverNode->Name.MaximumLength = Length;
  1889. RtlAppendUnicodeToString(&DriverNode->Name, Name);
  1890. //
  1891. // Tag/ErrorControl
  1892. //
  1893. DriverNode->Tag = Tag;
  1894. DriverNode->ErrorControl = ErrorControl;
  1895. if (InsertAtHead) {
  1896. InsertHeadList(BootDriverListHead, &DriverListEntry->Link);
  1897. } else {
  1898. InsertTailList(BootDriverListHead, &DriverListEntry->Link);
  1899. }
  1900. return ESUCCESS;
  1901. }
  1902. #define HFILE_TYPE_ALTERNATE 1 // alternate, in order for boot to be able to boot downlevel OSes
  1903. BOOLEAN
  1904. BlInitializeHive(
  1905. IN PVOID HiveImage,
  1906. IN PCMHIVE Hive,
  1907. IN BOOLEAN IsAlternate
  1908. )
  1909. /*++
  1910. Routine Description:
  1911. Initializes the hive data structure based on the in-memory hive image.
  1912. Arguments:
  1913. HiveImage - Supplies a pointer to the in-memory hive image.
  1914. Hive - Supplies the CMHIVE structure to be filled in.
  1915. IsAlternate - Supplies whether or not the hive is the alternate hive,
  1916. which indicates that the primary hive is corrupt and should be
  1917. rewritten by the system.
  1918. Return Value:
  1919. TRUE - Hive successfully initialized.
  1920. FALSE - Hive is corrupt.
  1921. --*/
  1922. {
  1923. NTSTATUS status;
  1924. ULONG HiveCheckCode;
  1925. status = HvInitializeHive(
  1926. &Hive->Hive,
  1927. HINIT_MEMORY_INPLACE,
  1928. FALSE,
  1929. IsAlternate ? HFILE_TYPE_ALTERNATE : HFILE_TYPE_PRIMARY,
  1930. HiveImage,
  1931. (PALLOCATE_ROUTINE)BlpHiveAllocate, // allocate
  1932. NULL, // free
  1933. NULL, // setsize
  1934. NULL, // write
  1935. NULL, // read
  1936. NULL, // flush
  1937. 1, // cluster
  1938. NULL
  1939. );
  1940. if (!NT_SUCCESS(status)) {
  1941. return FALSE;
  1942. }
  1943. HiveCheckCode = CmCheckRegistry(Hive,CM_CHECK_REGISTRY_LOADER_CLEAN|CM_CHECK_REGISTRY_HIVE_CHECK);
  1944. if (HiveCheckCode != 0) {
  1945. return(FALSE);
  1946. } else {
  1947. return TRUE;
  1948. }
  1949. }
  1950. PVOID
  1951. BlpHiveAllocate(
  1952. IN ULONG Length,
  1953. IN BOOLEAN UseForIo,
  1954. IN ULONG Tag
  1955. )
  1956. /*++
  1957. Routine Description:
  1958. Wrapper for hive allocation calls. It just calls BlAllocateHeap.
  1959. Arguments:
  1960. Length - Supplies the size of block required in bytes.
  1961. UseForIo - Supplies whether or not the memory is to be used for I/O
  1962. (this is currently ignored)
  1963. Return Value:
  1964. address of the block of memory
  1965. or
  1966. NULL if no memory available
  1967. --*/
  1968. {
  1969. UNREFERENCED_PARAMETER( Length );
  1970. UNREFERENCED_PARAMETER( UseForIo );
  1971. UNREFERENCED_PARAMETER( Tag );
  1972. return(BlAllocateHeap(Length));
  1973. }
  1974. NTSTATUS
  1975. HvLoadHive(
  1976. PHHIVE Hive
  1977. )
  1978. {
  1979. UNREFERENCED_PARAMETER(Hive);
  1980. return(STATUS_SUCCESS);
  1981. }
  1982. NTSTATUS
  1983. HvMapHive(
  1984. PHHIVE Hive
  1985. )
  1986. {
  1987. UNREFERENCED_PARAMETER(Hive);
  1988. return(STATUS_SUCCESS);
  1989. }
  1990. NTSTATUS
  1991. HvpAdjustHiveFreeDisplay(
  1992. IN PHHIVE Hive,
  1993. IN ULONG HiveLength,
  1994. IN HSTORAGE_TYPE Type
  1995. )
  1996. {
  1997. UNREFERENCED_PARAMETER(Hive);
  1998. UNREFERENCED_PARAMETER(HiveLength);
  1999. UNREFERENCED_PARAMETER(Type);
  2000. return(STATUS_SUCCESS);
  2001. }
  2002. VOID
  2003. HvpAddFreeCellHint(
  2004. PHHIVE Hive,
  2005. HCELL_INDEX Cell,
  2006. ULONG Index,
  2007. HSTORAGE_TYPE Type
  2008. )
  2009. {
  2010. UNREFERENCED_PARAMETER(Hive);
  2011. UNREFERENCED_PARAMETER(Cell);
  2012. UNREFERENCED_PARAMETER(Index);
  2013. UNREFERENCED_PARAMETER(Type);
  2014. }
  2015. VOID
  2016. HvpRemoveFreeCellHint(
  2017. PHHIVE Hive,
  2018. HCELL_INDEX Cell,
  2019. ULONG Index,
  2020. HSTORAGE_TYPE Type
  2021. )
  2022. {
  2023. UNREFERENCED_PARAMETER(Hive);
  2024. UNREFERENCED_PARAMETER(Cell);
  2025. UNREFERENCED_PARAMETER(Index);
  2026. UNREFERENCED_PARAMETER(Type);
  2027. }
  2028. HCELL_INDEX
  2029. HvpFindFreeCell(
  2030. PHHIVE Hive,
  2031. ULONG Index,
  2032. ULONG NewSize,
  2033. HSTORAGE_TYPE Type,
  2034. HCELL_INDEX Vicinity
  2035. )
  2036. {
  2037. UNREFERENCED_PARAMETER(Hive);
  2038. UNREFERENCED_PARAMETER(Index);
  2039. UNREFERENCED_PARAMETER(Type);
  2040. UNREFERENCED_PARAMETER(NewSize);
  2041. UNREFERENCED_PARAMETER(Vicinity);
  2042. return HCELL_NIL;
  2043. }
  2044. VOID
  2045. CmpTouchView(
  2046. IN PCMHIVE CmHive,
  2047. IN PCM_VIEW_OF_FILE CmView,
  2048. IN ULONG Cell
  2049. )
  2050. {
  2051. UNREFERENCED_PARAMETER(CmHive);
  2052. UNREFERENCED_PARAMETER(CmView);
  2053. UNREFERENCED_PARAMETER(Cell);
  2054. }
  2055. NTSTATUS
  2056. CmpMapThisBin(
  2057. PCMHIVE CmHive,
  2058. HCELL_INDEX Cell,
  2059. BOOLEAN Touch
  2060. )
  2061. {
  2062. UNREFERENCED_PARAMETER(CmHive);
  2063. UNREFERENCED_PARAMETER(Cell);
  2064. UNREFERENCED_PARAMETER(Touch);
  2065. return(STATUS_SUCCESS);
  2066. }
  2067. /*
  2068. NTSTATUS
  2069. CmpMapCmView(
  2070. IN PCMHIVE CmHive,
  2071. IN ULONG FileOffset,
  2072. OUT PCM_VIEW_OF_FILE *CmView
  2073. )
  2074. {
  2075. UNREFERENCED_PARAMETER(CmHive);
  2076. UNREFERENCED_PARAMETER(FileOffset);
  2077. UNREFERENCED_PARAMETER(CmView);
  2078. return(STATUS_SUCCESS);
  2079. }
  2080. VOID
  2081. CmpPinCmView (
  2082. IN PCMHIVE CmHive,
  2083. PCM_VIEW_OF_FILE CmView
  2084. )
  2085. {
  2086. UNREFERENCED_PARAMETER(CmHive);
  2087. UNREFERENCED_PARAMETER(CmView);
  2088. }
  2089. VOID
  2090. CmpUnPinCmView (
  2091. IN PCMHIVE CmHive,
  2092. IN PCM_VIEW_OF_FILE CmView,
  2093. IN BOOLEAN SetClean
  2094. )
  2095. {
  2096. UNREFERENCED_PARAMETER(CmHive);
  2097. UNREFERENCED_PARAMETER(CmView);
  2098. UNREFERENCED_PARAMETER(SetClean);
  2099. }
  2100. VOID
  2101. CmpLazyFlush(
  2102. VOID
  2103. )
  2104. {
  2105. }
  2106. */
  2107. /*
  2108. NTSTATUS
  2109. CmpDoFileSetSize(
  2110. PHHIVE Hive,
  2111. ULONG FileType,
  2112. ULONG FileSize
  2113. )
  2114. {
  2115. UNREFERENCED_PARAMETER(Hive);
  2116. UNREFERENCED_PARAMETER(FileType);
  2117. UNREFERENCED_PARAMETER(FileSize);
  2118. return(STATUS_SUCCESS);
  2119. }
  2120. */
  2121. BOOLEAN
  2122. HvMarkCellDirty(
  2123. PHHIVE Hive,
  2124. HCELL_INDEX Cell
  2125. )
  2126. {
  2127. UNREFERENCED_PARAMETER(Hive);
  2128. UNREFERENCED_PARAMETER(Cell);
  2129. return(TRUE);
  2130. }
  2131. BOOLEAN
  2132. HvMarkDirty(
  2133. PHHIVE Hive,
  2134. HCELL_INDEX Start,
  2135. ULONG Length,
  2136. BOOLEAN DirtyAndPin
  2137. )
  2138. {
  2139. UNREFERENCED_PARAMETER(Hive);
  2140. UNREFERENCED_PARAMETER(Start);
  2141. UNREFERENCED_PARAMETER(Length);
  2142. UNREFERENCED_PARAMETER(DirtyAndPin);
  2143. return(TRUE);
  2144. }
  2145. BOOLEAN
  2146. HvpDoWriteHive(
  2147. PHHIVE Hive,
  2148. ULONG FileType
  2149. )
  2150. {
  2151. UNREFERENCED_PARAMETER(Hive);
  2152. UNREFERENCED_PARAMETER(FileType);
  2153. return(TRUE);
  2154. }
  2155. BOOLEAN
  2156. HvpGrowLog1(
  2157. PHHIVE Hive,
  2158. ULONG Count
  2159. )
  2160. {
  2161. UNREFERENCED_PARAMETER(Hive);
  2162. UNREFERENCED_PARAMETER(Count);
  2163. return(TRUE);
  2164. }
  2165. BOOLEAN
  2166. HvpGrowLog2(
  2167. PHHIVE Hive,
  2168. ULONG Size
  2169. )
  2170. {
  2171. UNREFERENCED_PARAMETER(Hive);
  2172. UNREFERENCED_PARAMETER(Size);
  2173. return(TRUE);
  2174. }
  2175. BOOLEAN
  2176. CmpValidateHiveSecurityDescriptors(
  2177. IN PHHIVE Hive,
  2178. OUT PBOOLEAN ResetSD
  2179. )
  2180. {
  2181. UNREFERENCED_PARAMETER(Hive);
  2182. UNREFERENCED_PARAMETER( ResetSD );
  2183. return(TRUE);
  2184. }
  2185. BOOLEAN
  2186. CmpTestRegistryLock()
  2187. {
  2188. return TRUE;
  2189. }
  2190. BOOLEAN
  2191. CmpTestRegistryLockExclusive()
  2192. {
  2193. return TRUE;
  2194. }
  2195. BOOLEAN
  2196. HvIsBinDirty(
  2197. IN PHHIVE Hive,
  2198. IN HCELL_INDEX Cell
  2199. )
  2200. {
  2201. UNREFERENCED_PARAMETER( Hive );
  2202. UNREFERENCED_PARAMETER( Cell );
  2203. return(FALSE);
  2204. }
  2205. PHBIN
  2206. HvpAddBin(
  2207. IN PHHIVE Hive,
  2208. IN ULONG NewSize,
  2209. IN HSTORAGE_TYPE Type
  2210. )
  2211. {
  2212. UNREFERENCED_PARAMETER( Hive );
  2213. UNREFERENCED_PARAMETER( NewSize );
  2214. UNREFERENCED_PARAMETER( Type );
  2215. return(NULL);
  2216. }
  2217. VOID
  2218. CmpReleaseGlobalQuota(
  2219. IN ULONG Size
  2220. )
  2221. {
  2222. UNREFERENCED_PARAMETER( Size );
  2223. return;
  2224. }
  2225. #if DOCKINFO_VERBOSE
  2226. VOID
  2227. BlDiagDisplayProfileList(
  2228. IN PCM_HARDWARE_PROFILE_LIST ProfileList,
  2229. IN PCM_HARDWARE_PROFILE_ALIAS_LIST AliasList,
  2230. IN BOOLEAN WaitForUserInput
  2231. )
  2232. /*++
  2233. Routine Description:
  2234. This is a diagnostic function only!
  2235. Display hardware profile list on console, optionally wait for user
  2236. input before proceeding.
  2237. Arguments:
  2238. ProfileList - Supplies a list of hardware profiles to display
  2239. WaitForUserInput - Prompt user to hit a key ('y') to continue, and wait
  2240. for user's input if TRUE. Don't wait if FALSE.
  2241. Return Value:
  2242. None.
  2243. --*/
  2244. {
  2245. TCHAR Buffer[200];
  2246. TCHAR StrFriendlyName[30];
  2247. PTCHAR AliasType [] = {
  2248. TEXT("NotAliasable"), // 0
  2249. TEXT("Aliasable "), // 1
  2250. TEXT("True Match "), // 2
  2251. TEXT("True & Alias"), // 3
  2252. TEXT("Pristine "), // 4
  2253. TEXT("Pris & Alias"), // 5
  2254. TEXT("Pris & True "), // 6
  2255. TEXT("P & A & T ") // 7
  2256. };
  2257. ULONG Count;
  2258. ULONG i;
  2259. // display header
  2260. _stprintf(Buffer, TEXT("Profiles: <PrefOrd, Id - Aliased FriendlyName>\r\n\0"));
  2261. ArcWrite(BlConsoleOutDeviceId, Buffer, _tcslen(Buffer)*sizeof(TCHAR), &Count);
  2262. // for each hardware profile
  2263. for (i = 0; i < ProfileList->CurrentProfileCount; ++i) {
  2264. #ifdef UNICODE
  2265. wcsncpy(
  2266. StrFriendlyName,
  2267. ProfileList->Profile[i].FriendlyName,
  2268. ProfileList->Profile[i].NameLength,
  2269. );
  2270. StrFriendlyName[29] = L'\0';
  2271. StrFriendlyName[ProfileList->Profile[i].NameLength] = L'\0';
  2272. #else
  2273. // copy and convert unicode fields to ascii for output
  2274. RtlUnicodeToMultiByteN(StrFriendlyName,
  2275. sizeof(StrFriendlyName),
  2276. &Count,
  2277. ProfileList->Profile[i].FriendlyName,
  2278. ProfileList->Profile[i].NameLength);
  2279. StrFriendlyName[Count] = '\0';
  2280. #endif
  2281. // display info for current profile
  2282. _stprintf(Buffer,
  2283. TEXT(" <%2ld> %2ld - %s \"%s\"\r\n\0"),
  2284. ProfileList->Profile[i].PreferenceOrder,
  2285. ProfileList->Profile[i].Id,
  2286. AliasType[ ProfileList->Profile[i].Flags ],
  2287. StrFriendlyName);
  2288. ArcWrite(
  2289. BlConsoleOutDeviceId,
  2290. Buffer,
  2291. _tcslen(Buffer)*sizeof(TCHAR),
  2292. &Count );
  2293. }
  2294. // display header
  2295. _stprintf(Buffer, TEXT("Aliases: <Profile #> DockState [DockID, SerialNumber]\r\n\0"));
  2296. ArcWrite(BlConsoleOutDeviceId, Buffer, _tcslen(Buffer)*sizeof(TCHAR), &Count);
  2297. if (AliasList) {
  2298. for (i = 0; i < AliasList->CurrentAliasCount; i++) {
  2299. _stprintf(Buffer, TEXT(" <%2ld> %x [%x, %x]\r\n\0"),
  2300. AliasList->Alias[i].ProfileNumber,
  2301. AliasList->Alias[i].DockState,
  2302. AliasList->Alias[i].DockID,
  2303. AliasList->Alias[i].SerialNumber);
  2304. ArcWrite(BlConsoleOutDeviceId, Buffer, _tcslen(Buffer)*sizeof(TCHAR), &Count);
  2305. }
  2306. }
  2307. if(WaitForUserInput) {
  2308. #ifdef EFI
  2309. //
  2310. // disable efi watchdog when waiting for user input
  2311. //
  2312. DisableEFIWatchDog();
  2313. #endif
  2314. // display prompt and wait for user input to continue
  2315. _stprintf(Buffer, TEXT("press 'y' (lowercase) to continue...\r\n\0"));
  2316. ArcWrite(BlConsoleOutDeviceId, Buffer, _tcslen(Buffer)*sizeof(TCHAR), &Count);
  2317. while (BlGetKey() != 'y') {
  2318. //
  2319. // nothing
  2320. //
  2321. }
  2322. #ifdef EFI
  2323. //
  2324. // reset efi watchdog
  2325. //
  2326. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  2327. #endif
  2328. }
  2329. }
  2330. #endif
  2331. VOID
  2332. BlDockInfoFilterDockingState(
  2333. IN OUT PCM_HARDWARE_PROFILE_LIST ProfileList,
  2334. IN OUT PCM_HARDWARE_PROFILE_ALIAS_LIST AliasList,
  2335. IN ULONG DockingState,
  2336. IN ULONG DockID,
  2337. IN ULONG SerialNumber
  2338. )
  2339. /*++
  2340. Routine Description:
  2341. Discard all hardware profiles that do not have the
  2342. DOCKINFO_UNDOCKED bit set in the DockState field
  2343. Arguments:
  2344. ProfileList - Supplies a list of hardware profiles.
  2345. Returns a list containing a subset of the supplied
  2346. hardware profiles.
  2347. Return Value:
  2348. None.
  2349. --*/
  2350. {
  2351. ULONG i = 0;
  2352. ULONG j;
  2353. ULONG len;
  2354. ULONG mask = HW_PROFILE_DOCKSTATE_UNDOCKED | HW_PROFILE_DOCKSTATE_DOCKED;
  2355. BOOLEAN trueMatch = FALSE;
  2356. #if DOCKINFO_VERBOSE
  2357. TCHAR buffer[200];
  2358. ULONG count;
  2359. #endif
  2360. if (AliasList) {
  2361. while (i < AliasList->CurrentAliasCount) {
  2362. if (((AliasList->Alias[i].DockState & mask) != 0) &&
  2363. ((AliasList->Alias[i].DockState & mask) != DockingState)) {
  2364. //
  2365. // This alias claims to be docked or undocked, but does not
  2366. // match the current state. Therefore skip it.
  2367. //
  2368. ;
  2369. } else if ((AliasList->Alias[i].DockID == DockID) &&
  2370. (AliasList->Alias[i].SerialNumber == SerialNumber)) {
  2371. //
  2372. // This alias matches so mark the profile.
  2373. //
  2374. for (j = 0; j < ProfileList->CurrentProfileCount; j++) {
  2375. if (ProfileList->Profile[j].Id ==
  2376. AliasList->Alias[i].ProfileNumber) {
  2377. ProfileList->Profile[j].Flags =
  2378. CM_HP_FLAGS_TRUE_MATCH;
  2379. trueMatch = TRUE;
  2380. }
  2381. }
  2382. }
  2383. i++;
  2384. }
  2385. }
  2386. #if DOCKINFO_VERBOSE
  2387. _stprintf(buffer, TEXT("Filtering Profiles ...\r\n\0"));
  2388. ArcWrite(BlConsoleOutDeviceId, buffer, _tcslen(buffer)*sizeof(TCHAR), &count);
  2389. #endif
  2390. i = 0;
  2391. while (i < ProfileList->CurrentProfileCount) {
  2392. if ((ProfileList->Profile[i].Flags & CM_HP_FLAGS_PRISTINE) &&
  2393. !trueMatch &&
  2394. AliasList) {
  2395. //
  2396. // Leave this one in the list
  2397. //
  2398. i++;
  2399. continue;
  2400. } else if (ProfileList->Profile[i].Flags & CM_HP_FLAGS_ALIASABLE) {
  2401. //
  2402. // Leave this one in the list
  2403. //
  2404. i++;
  2405. continue;
  2406. } else if (ProfileList->Profile[i].Flags & CM_HP_FLAGS_TRUE_MATCH) {
  2407. //
  2408. // Leave this one in the list
  2409. //
  2410. i++;
  2411. continue;
  2412. }
  2413. //
  2414. // discard this profile by (1) shifting remaining profiles in
  2415. // array to fill in the space of this discarded profile
  2416. // and (2) decrementing profile count
  2417. //
  2418. len = ProfileList->CurrentProfileCount - i - 1;
  2419. if (0 < len) {
  2420. RtlMoveMemory(&ProfileList->Profile[i],
  2421. &ProfileList->Profile[i+1],
  2422. sizeof(CM_HARDWARE_PROFILE) * len);
  2423. }
  2424. --ProfileList->CurrentProfileCount;
  2425. }
  2426. }
  2427. VOID
  2428. BlDockInfoFilterProfileList(
  2429. IN OUT PCM_HARDWARE_PROFILE_LIST ProfileList,
  2430. IN OUT PCM_HARDWARE_PROFILE_ALIAS_LIST AliasList
  2431. )
  2432. /*++
  2433. Routine Description:
  2434. Filters hardware profile list by discarding hardware profiles that
  2435. do not match the docking station information returned by NTDETECT.
  2436. Arguments:
  2437. ProfileList - Supplies a list of hardware profiles.
  2438. - Returns a list containing a subset of the supplied
  2439. hardware profiles.
  2440. Return Value:
  2441. None.
  2442. --*/
  2443. {
  2444. #if DOCKINFO_VERBOSE
  2445. // display ProfileList prior to filtering
  2446. BlDiagDisplayProfileList(ProfileList, AliasList, TRUE);
  2447. #endif
  2448. if (1 == ProfileList->CurrentProfileCount) {
  2449. if (ProfileList->Profile[0].Flags & CM_HP_FLAGS_PRISTINE) {
  2450. //
  2451. // Nothing to filter.
  2452. //
  2453. return;
  2454. }
  2455. }
  2456. BlDockInfoFilterDockingState (
  2457. ProfileList,
  2458. AliasList,
  2459. BlLoaderBlock->Extension->Profile.DockingState,
  2460. BlLoaderBlock->Extension->Profile.DockID,
  2461. BlLoaderBlock->Extension->Profile.SerialNumber);
  2462. #if DOCKINFO_VERBOSE
  2463. // display ProfileList prior to filtering
  2464. BlDiagDisplayProfileList(ProfileList, AliasList, TRUE);
  2465. #endif
  2466. }
  2467. int
  2468. BlIsReturnToOSChoicesValid(
  2469. VOID
  2470. )
  2471. /*++
  2472. Routine Description:
  2473. Indicates whether the "Return to OS Choices Menu" should
  2474. be shown as advanced boot option or not.
  2475. Arguments:
  2476. None
  2477. Return Value:
  2478. 1 if yes otherwise 0.
  2479. --*/
  2480. {
  2481. return BlShowReturnToOSChoices;
  2482. }