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.

3139 lines
94 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Spntfix.c
  5. Abstract:
  6. This module contains code to repair winnt installations.
  7. Author:
  8. Shie-Lin Tzong (shielint) 27-Jan-1994
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. //
  14. // Path to the ntuser.dat hive
  15. //
  16. #define DEFAULT_USER_PATH L"Users\\Default User"
  17. //
  18. // Global variables control which repair options should be performed.
  19. // Initialized to ALL options. We explicitly use 1 and 0 for true and false.
  20. //
  21. #if defined(_AMD64_) || defined(_X86_)
  22. ULONG RepairItems[RepairItemMax] = { 0, 0, 0}; // BCL - Seagate - removed one.
  23. #else
  24. ULONG RepairItems[RepairItemMax] = { 0, 0}; // BCL
  25. #endif // defined(_AMD64_) || defined(_X86_)
  26. PVOID RepairGauge = NULL;
  27. //
  28. // global variables for delayed driver CAB opening during
  29. // repair
  30. //
  31. extern PWSTR gszDrvInfDeviceName;
  32. extern PWSTR gszDrvInfDirName;
  33. extern HANDLE ghSif;
  34. #define FILE_ATTRIBUTES_RHS (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)
  35. //**************************************************************
  36. // S E L E C T I N G N T T O REPAIR S T U F F
  37. //**************************************************************
  38. #define MENU_LEFT_X 3
  39. #define MENU_WIDTH (VideoVars.ScreenWidth-(2*MENU_LEFT_X))
  40. #define LIST_BOX_WIDTH 50
  41. #define LIST_BOX_HEIGHT RepairItemMax+1
  42. #define HIVE_LIST_BOX_WIDTH 45
  43. #define HIVE_LIST_BOX_HEIGHT RepairHiveMax+1
  44. #define MENU_INDENT 4
  45. VOID
  46. SppGetRepairPathInformation(
  47. IN PVOID LogFileHandle,
  48. OUT PWSTR *SystemPartition,
  49. OUT PWSTR *SystemPartitionDirectory,
  50. OUT PWSTR *WinntPartition,
  51. OUT PWSTR *WinntPartitionDirectory
  52. )
  53. /*++
  54. Routine Description:
  55. This goes through the list of NTs on the system and finds out which are
  56. repairable. Presents the information to the user.
  57. Arguments:
  58. SifHandle - Handle the txtsetup.sif
  59. SystemPartition - Supplies a variable to receive the name of System
  60. partition.
  61. SystemPartitionDirectory - Supplies a variable to receive the name of
  62. the osloader directory on the system partition.
  63. WinntPartition - Supplies a variable to receive the name of winnt
  64. partition.
  65. WinntPartitionDirectory - Supplies a variable to receive the winnt
  66. directory.
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. PWSTR KeyName = NULL;
  72. *SystemPartition = SpGetSectionKeyIndex (LogFileHandle,
  73. SIF_NEW_REPAIR_PATHS,
  74. SIF_NEW_REPAIR_PATHS_SYSTEM_PARTITION_DEVICE,
  75. 0);
  76. if (*SystemPartition == NULL) {
  77. KeyName = SIF_NEW_REPAIR_PATHS_SYSTEM_PARTITION_DEVICE;
  78. goto ReportError;
  79. }
  80. *SystemPartitionDirectory = SpGetSectionKeyIndex (LogFileHandle,
  81. SIF_NEW_REPAIR_PATHS,
  82. SIF_NEW_REPAIR_PATHS_SYSTEM_PARTITION_DIRECTORY,
  83. 0);
  84. if (*SystemPartitionDirectory == NULL) {
  85. KeyName = SIF_NEW_REPAIR_PATHS_SYSTEM_PARTITION_DIRECTORY;
  86. goto ReportError;
  87. }
  88. *WinntPartition = SpGetSectionKeyIndex ( LogFileHandle,
  89. SIF_NEW_REPAIR_PATHS,
  90. SIF_NEW_REPAIR_PATHS_TARGET_DEVICE,
  91. 0);
  92. if (*WinntPartition == NULL) {
  93. KeyName = SIF_NEW_REPAIR_PATHS_TARGET_DEVICE;
  94. goto ReportError;
  95. }
  96. *WinntPartitionDirectory = SpGetSectionKeyIndex (LogFileHandle,
  97. SIF_NEW_REPAIR_PATHS,
  98. SIF_NEW_REPAIR_PATHS_TARGET_DIRECTORY,
  99. 0);
  100. if (*WinntPartitionDirectory == NULL) {
  101. KeyName = SIF_NEW_REPAIR_PATHS_TARGET_DIRECTORY;
  102. goto ReportError;
  103. }
  104. ReportError:
  105. if (KeyName) {
  106. //
  107. // Unable to find path information. This indicates the setup.log
  108. // is bad. Inform user and exit.
  109. //
  110. SpFatalSifError(LogFileHandle,SIF_NEW_REPAIR_PATHS,KeyName,0,0);
  111. }
  112. }
  113. BOOLEAN
  114. SpFindNtToRepair(
  115. IN PVOID SifHandle,
  116. OUT PDISK_REGION *TargetRegion,
  117. OUT PWSTR *TargetPath,
  118. OUT PDISK_REGION *SystemPartitionRegion,
  119. OUT PWSTR *SystemPartitionDirectory,
  120. OUT PBOOLEAN RepairableBootSetsFound
  121. )
  122. /*++
  123. Routine Description:
  124. This goes through the list of NTs on the system and finds out which are
  125. repairable. Presents the information to the user.
  126. Arguments:
  127. SifHandle: Handle the txtsetup.sif
  128. TargetRegion: Variable to receive the partition of the Windows NT to install
  129. NULL if not chosen.
  130. TargetPath: Variable to receive the target path of Windows NT. NULL if
  131. not decided.
  132. SystemPartitionRegion:
  133. Variable to receive the system partition of the Windows NT
  134. SystemPartitionDirectory:
  135. Variable to receive the osloader directory of the system
  136. partition.
  137. RepairableBootSetsFound:
  138. Indicates whether a repairable boot set was found. This
  139. information can be used by the caller when the function
  140. returns FALSE, so that the caller can determine if no
  141. repairable disk was found, or if the user didn't select
  142. any of the repairable systems found.
  143. Return Value:
  144. A boolean value to indicate if selection has been made.
  145. --*/
  146. {
  147. NT_PRODUCT_TYPE ProductType;
  148. BOOLEAN GoRepair = FALSE;
  149. NTSTATUS NtStatus;
  150. ULONG j, RepairBootSets = 0, MajorVersion, MinorVersion, BuildNumber, ProductSuiteMask;
  151. PSP_BOOT_ENTRY BootEntry;
  152. PSP_BOOT_ENTRY ChosenBootEntry;
  153. LCID LangId;
  154. UPG_PROGRESS_TYPE UpgradeProgressValue;
  155. //
  156. // Find all upgradeable boot entries. These are entries that are unique in
  157. // the boot entry list and are present on disk.
  158. //
  159. SpDetermineUniqueAndPresentBootEntries();
  160. for ( BootEntry = SpBootEntries; BootEntry != NULL ; BootEntry = BootEntry->Next ) {
  161. if (!BootEntry->Processable) {
  162. continue;
  163. }
  164. //
  165. // Reinitialize
  166. //
  167. BootEntry->Processable = FALSE;
  168. LangId = -1;
  169. //
  170. // try loading the registry and getting the following information
  171. // out of it:
  172. //
  173. // 1) Product type: WINNT | LANMANNT
  174. // 2) Major and Minor Version Number
  175. //
  176. // Based on the information, we will update the RepairableList.
  177. //
  178. NtStatus = SpDetermineProduct(
  179. BootEntry->OsPartitionDiskRegion,
  180. BootEntry->OsDirectory,
  181. &ProductType,
  182. &MajorVersion,
  183. &MinorVersion,
  184. &BuildNumber,
  185. &ProductSuiteMask,
  186. &UpgradeProgressValue,
  187. NULL,
  188. NULL, // Pid is not needed
  189. NULL, // ignore eval variation flag
  190. &LangId, // Language Id
  191. NULL // service pack not needed?
  192. );
  193. if(NT_SUCCESS(NtStatus)) {
  194. //
  195. // make sure we only try to repair a build that matches the CD we have inserted
  196. //
  197. BootEntry->Processable = SpDoBuildsMatch(
  198. SifHandle,
  199. BuildNumber,
  200. ProductType,
  201. ProductSuiteMask,
  202. AdvancedServer,
  203. SuiteType,
  204. LangId
  205. );
  206. if( BootEntry->Processable ) {
  207. RepairBootSets++;
  208. ChosenBootEntry = BootEntry;
  209. }
  210. }
  211. }
  212. //
  213. // Find out how many valid boot sets there are which we can repair
  214. //
  215. *RepairableBootSetsFound = (RepairBootSets != 0);
  216. if ( RepairBootSets == 1 ) {
  217. //
  218. // If it is a fresh attempt at upgrade ask the user if he
  219. // wants to upgrade or not
  220. //
  221. GoRepair = SppSelectNTSingleRepair(
  222. ChosenBootEntry->OsPartitionDiskRegion,
  223. ChosenBootEntry->OsDirectory,
  224. ChosenBootEntry->FriendlyName
  225. );
  226. } else if (RepairBootSets > 1) {
  227. //
  228. // Find out if the user wants to upgrade one of the Windows
  229. // NT found
  230. //
  231. GoRepair = SppSelectNTMultiRepair(
  232. &ChosenBootEntry
  233. );
  234. }
  235. //
  236. // Depending on upgrade selection made do the setup needed before
  237. // we do the upgrade
  238. //
  239. if (GoRepair) {
  240. PWSTR p1,p2,p3;
  241. ULONG u;
  242. //
  243. // Return the region we are goint to repair
  244. //
  245. *TargetRegion = ChosenBootEntry->OsPartitionDiskRegion;
  246. *TargetPath = SpDupStringW(ChosenBootEntry->OsDirectory);
  247. *SystemPartitionRegion = ChosenBootEntry->LoaderPartitionDiskRegion;
  248. //
  249. // Process the osloader variable to extract the system partition path.
  250. // The var vould be of the form ...partition(1)\os\nt\... or
  251. // ...partition(1)os\nt\...
  252. // So we search forward for the first \ and then backwards for
  253. // the closest ) to find the start of the directory. We then
  254. // search backwards in the resulting string for the last \ to find
  255. // the end of the directory.
  256. //
  257. p1 = ChosenBootEntry->LoaderFile;
  258. p2 = wcsrchr(p1, L'\\');
  259. if (p2 == NULL) {
  260. p2 = p1;
  261. }
  262. u = (ULONG)(p2 - p1);
  263. if(u == 0) {
  264. *SystemPartitionDirectory = SpDupStringW(L"");
  265. } else {
  266. p2 = p3 = SpMemAlloc((u+2)*sizeof(WCHAR));
  267. ASSERT(p3);
  268. if(*p1 != L'\\') {
  269. *p3++ = L'\\';
  270. }
  271. wcsncpy(p3, p1, u);
  272. p3[u] = 0;
  273. *SystemPartitionDirectory = p2;
  274. }
  275. }
  276. //
  277. // Do cleanup
  278. //
  279. CLEAR_CLIENT_SCREEN();
  280. return (GoRepair);
  281. }
  282. BOOLEAN
  283. SppSelectNTSingleRepair(
  284. IN PDISK_REGION Region,
  285. IN PWSTR OsLoadFileName,
  286. IN PWSTR LoadIdentifier
  287. )
  288. /*++
  289. Routine Description:
  290. Inform a user that Setup has found a previous Windows NT installation.
  291. The user has the option to repair this or cancel.
  292. Arguments:
  293. Region - Region descriptor for the NT found
  294. OsLoadFileName - Directory for the NT found
  295. LoadIdentifier - Multi boot load identifier used for this NT.
  296. Return Value:
  297. --*/
  298. {
  299. ULONG ValidKeys[] = { KEY_F3,ASCI_CR, ASCI_ESC, 0 };
  300. ULONG c;
  301. PWSTR TmpString = NULL;
  302. ASSERT(Region->PartitionedSpace);
  303. ASSERT(wcslen(OsLoadFileName) >= 2);
  304. if( Region->DriveLetter ) {
  305. swprintf( TemporaryBuffer,
  306. L"%wc:%ws",
  307. Region->DriveLetter,
  308. OsLoadFileName );
  309. TmpString = SpDupStringW( TemporaryBuffer );
  310. }
  311. while(1) {
  312. SpStartScreen(
  313. SP_SCRN_WINNT_REPAIR,
  314. 3,
  315. HEADER_HEIGHT+1,
  316. FALSE,
  317. FALSE,
  318. DEFAULT_ATTRIBUTE,
  319. (Region->DriveLetter)? TmpString : OsLoadFileName,
  320. LoadIdentifier
  321. );
  322. SpDisplayStatusOptions(
  323. DEFAULT_STATUS_ATTRIBUTE,
  324. SP_STAT_F3_EQUALS_EXIT,
  325. SP_STAT_ESC_EQUALS_CANCEL,
  326. SP_STAT_ENTER_EQUALS_REPAIR,
  327. 0
  328. );
  329. if( TmpString != NULL ) {
  330. SpMemFree( TmpString );
  331. }
  332. switch(c=SpWaitValidKey(ValidKeys,NULL,NULL)) {
  333. case KEY_F3:
  334. SpConfirmExit();
  335. break;
  336. case ASCI_CR:
  337. return(TRUE);
  338. default:
  339. //
  340. // must have entered ESC
  341. //
  342. return(FALSE);
  343. }
  344. }
  345. }
  346. BOOLEAN
  347. SppSelectNTMultiRepair(
  348. OUT PSP_BOOT_ENTRY *BootEntryChosen
  349. )
  350. {
  351. PVOID Menu;
  352. ULONG MenuTopY;
  353. ULONG ValidKeys[] = { KEY_F3, ASCI_CR, ASCI_ESC, 0 };
  354. ULONG Keypress;
  355. PSP_BOOT_ENTRY BootEntry,FirstRepairSet;
  356. while(1) {
  357. //
  358. // Display the text that goes above the menu on the partitioning screen.
  359. //
  360. SpDisplayScreen(SP_SCRN_WINNT_REPAIR_LIST,3,CLIENT_TOP+1);
  361. //
  362. // Calculate menu placement. Leave one blank line
  363. // and one line for a frame.
  364. //
  365. MenuTopY = NextMessageTopLine + (SplangQueryMinimizeExtraSpacing() ? 2 : 5);
  366. //
  367. // Create a menu.
  368. //
  369. Menu = SpMnCreate(
  370. MENU_LEFT_X,
  371. MenuTopY,
  372. MENU_WIDTH,
  373. VideoVars.ScreenHeight-MenuTopY-2-STATUS_HEIGHT
  374. );
  375. ASSERT(Menu);
  376. //
  377. // Build up a menu of partitions and free spaces.
  378. //
  379. FirstRepairSet = NULL;
  380. for(BootEntry = SpBootEntries; BootEntry != NULL; BootEntry = BootEntry->Next ) {
  381. if( BootEntry->Processable ) {
  382. if( BootEntry->OsPartitionDiskRegion->DriveLetter ) {
  383. swprintf(
  384. TemporaryBuffer,
  385. L"%wc:%ws %ws",
  386. BootEntry->OsPartitionDiskRegion->DriveLetter,
  387. BootEntry->OsDirectory,
  388. BootEntry->FriendlyName
  389. );
  390. } else {
  391. swprintf(
  392. TemporaryBuffer,
  393. L"%ws %ws",
  394. BootEntry->OsDirectory,
  395. BootEntry->FriendlyName
  396. );
  397. }
  398. SpMnAddItem(Menu,
  399. TemporaryBuffer,
  400. MENU_LEFT_X+MENU_INDENT,
  401. MENU_WIDTH-(2*MENU_INDENT),
  402. TRUE,
  403. (ULONG_PTR)BootEntry
  404. );
  405. if(FirstRepairSet == NULL) {
  406. FirstRepairSet = BootEntry;
  407. }
  408. }
  409. }
  410. //
  411. // Initialize the status line.
  412. //
  413. SpDisplayStatusOptions(
  414. DEFAULT_STATUS_ATTRIBUTE,
  415. SP_STAT_F3_EQUALS_EXIT,
  416. SP_STAT_ESC_EQUALS_CANCEL,
  417. SP_STAT_ENTER_EQUALS_REPAIR,
  418. 0
  419. );
  420. //
  421. // Display the menu
  422. //
  423. SpMnDisplay(
  424. Menu,
  425. (ULONG_PTR)FirstRepairSet,
  426. TRUE,
  427. ValidKeys,
  428. NULL,
  429. NULL,
  430. NULL,
  431. &Keypress,
  432. (PULONG_PTR)BootEntryChosen
  433. );
  434. //
  435. // Now act on the user's selection.
  436. //
  437. switch(Keypress) {
  438. case KEY_F3:
  439. SpConfirmExit();
  440. break;
  441. case ASCI_CR:
  442. SpMnDestroy(Menu);
  443. return( TRUE );
  444. default:
  445. SpMnDestroy(Menu);
  446. return(FALSE);
  447. }
  448. SpMnDestroy(Menu);
  449. }
  450. }
  451. VOID
  452. SppRepairScreenRepaint(
  453. IN PWSTR FullSourcename, OPTIONAL
  454. IN PWSTR FullTargetname, OPTIONAL
  455. IN BOOLEAN RepaintEntireScreen
  456. )
  457. {
  458. UNREFERENCED_PARAMETER(FullTargetname);
  459. UNREFERENCED_PARAMETER(FullSourcename);
  460. //
  461. // Repaint the entire screen if necessary.
  462. //
  463. if(RepaintEntireScreen) {
  464. if( SpDrEnabled() ) {
  465. SpStartScreen( SP_SCRN_ASR_IS_EXAMINING, 0, 6, TRUE, FALSE, DEFAULT_ATTRIBUTE );
  466. }
  467. else {
  468. SpStartScreen( SP_SCRN_SETUP_IS_EXAMINING,0, 6, TRUE, FALSE, DEFAULT_ATTRIBUTE );
  469. }
  470. if(RepairGauge) {
  471. SpDrawGauge(RepairGauge);
  472. }
  473. }
  474. }
  475. BOOLEAN
  476. SpErDiskScreen(
  477. BOOLEAN *HasErDisk
  478. )
  479. /*++
  480. Routine Description:
  481. Ask user if user has emergency repair disk.
  482. Arguments:
  483. *HasErDisk - Indicates whether diskette will be used.
  484. Return Value:
  485. TRUE - User chose disk or diskless.
  486. FALSE - User wants to return to previous screen.
  487. --*/
  488. {
  489. ULONG ValidKeys[] = { KEY_F3, ASCI_CR, ASCI_ESC, 0 };
  490. ULONG MnemonicKeys[] = { MnemonicLocate, 0 };
  491. BOOLEAN Choosing;
  492. ULONG c;
  493. for (Choosing = TRUE; Choosing; ) {
  494. SpDisplayScreen(SP_SCRN_REPAIR_ASK_REPAIR_DISK,3,4);
  495. SpDisplayStatusOptions(
  496. DEFAULT_STATUS_ATTRIBUTE,
  497. SP_STAT_ENTER_EQUALS_CONTINUE,
  498. SP_STAT_L_EQUALS_LOCATE,
  499. SP_STAT_ESC_EQUALS_CANCEL,
  500. SP_STAT_F3_EQUALS_EXIT,
  501. 0
  502. );
  503. //
  504. // Wait for keypress. Valid keys:
  505. //
  506. // L = Do not use ER diskette, locate on hard disk
  507. // F3 = exit
  508. // ENTER = Use ER diskette
  509. // ESC = cancel, return to previous screen
  510. //
  511. SpInputDrain();
  512. switch(c=SpWaitValidKey(ValidKeys,NULL,MnemonicKeys)) {
  513. case ASCI_CR:
  514. //
  515. // User wants express setup.
  516. //
  517. *HasErDisk = TRUE;
  518. Choosing = FALSE;
  519. break;
  520. case (MnemonicLocate | KEY_MNEMONIC):
  521. //
  522. // User wants repair without diskette.
  523. //
  524. *HasErDisk = FALSE;
  525. Choosing = FALSE;
  526. break;
  527. case KEY_F3:
  528. //
  529. // User wants to exit.
  530. //
  531. SpConfirmExit();
  532. break;
  533. default:
  534. //
  535. // must be ESC
  536. //
  537. *HasErDisk = FALSE;
  538. Choosing = FALSE;
  539. return( FALSE );
  540. }
  541. }
  542. return( TRUE );
  543. }
  544. BOOLEAN
  545. SppRepairReportError(
  546. IN BOOLEAN AllowEsc,
  547. IN ULONG ErrorScreenId,
  548. IN ULONG SubErrorId,
  549. IN PWSTR SectionName,
  550. IN ULONG LineNumber,
  551. IN PBOOLEAN DoNotPromptAgain
  552. )
  553. /*++
  554. Routine Description:
  555. Inform a user that repair has encountered some kind of error.
  556. The user has the option to continue or exit.
  557. Arguments:
  558. AllowEsc - Supplies a BOOLEAN to indicate if ESC is allowed.
  559. ErrorScreenId - The SCREEN error message number.
  560. SubErrorId - the sub error number
  561. SectionName - the name of the section which error occured.
  562. LineNumber - the error line number within the specified section.
  563. Return Value:
  564. FALSE if ESC was pressed.
  565. --*/
  566. {
  567. ULONG ValidKeys0[] = { KEY_F3, ASCI_CR, 0 };
  568. ULONG ValidKeys1[] = { KEY_F3, ASCI_CR, ASCI_ESC, 0 };
  569. ULONG MnemonicKeys[] = { MnemonicRepairAll, 0 };
  570. PULONG ValidKeys;
  571. PULONG Mnemonics;
  572. ULONG c;
  573. PWSTR SubError;
  574. BOOLEAN rc;
  575. SubError = SpMemAlloc(512);
  576. //
  577. // Line numbers are 0-based. Want to display to user as 1-based.
  578. //
  579. LineNumber++;
  580. //
  581. // Fetch/format the suberror.
  582. //
  583. SpFormatMessage(SubError, 512, SubErrorId, SectionName, LineNumber);
  584. //
  585. // Display the error screen.
  586. //
  587. SpStartScreen(
  588. ErrorScreenId,
  589. 3,
  590. HEADER_HEIGHT+1,
  591. FALSE,
  592. FALSE,
  593. DEFAULT_ATTRIBUTE,
  594. SubError
  595. );
  596. SpMemFree(SubError);
  597. //
  598. // Display status options: enter to continue.
  599. //
  600. if (AllowEsc) {
  601. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,
  602. SP_STAT_ENTER_EQUALS_CONTINUE,
  603. SP_STAT_A_EQUALS_REPAIR_ALL,
  604. SP_STAT_ESC_EQUALS_SKIP_FILE,
  605. SP_STAT_F3_EQUALS_EXIT,
  606. 0);
  607. ValidKeys = ValidKeys1;
  608. Mnemonics = MnemonicKeys;
  609. if( DoNotPromptAgain != NULL ) {
  610. *DoNotPromptAgain = FALSE;
  611. }
  612. } else {
  613. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,
  614. SP_STAT_ENTER_EQUALS_CONTINUE,
  615. SP_STAT_F3_EQUALS_EXIT,
  616. 0);
  617. ValidKeys = ValidKeys0;
  618. Mnemonics = NULL;
  619. }
  620. //
  621. // Wait for the user to press enter.
  622. //
  623. switch(c=SpWaitValidKey(ValidKeys,NULL,Mnemonics)) {
  624. case KEY_F3:
  625. SpConfirmExit();
  626. break;
  627. case ASCI_CR:
  628. rc = TRUE;
  629. break;
  630. case ASCI_ESC:
  631. rc = FALSE;
  632. break;
  633. default:
  634. //
  635. // must be repair all mnemonic
  636. //
  637. ASSERT(c == (MnemonicRepairAll | KEY_MNEMONIC));
  638. if( DoNotPromptAgain != NULL ) {
  639. *DoNotPromptAgain = TRUE;
  640. }
  641. rc = TRUE;
  642. break;
  643. }
  644. CLEAR_CLIENT_SCREEN();
  645. return(rc);
  646. }
  647. BOOLEAN
  648. SpLoadRepairLogFile(
  649. IN PWCHAR Filename,
  650. OUT PVOID *Handle
  651. )
  652. /*++
  653. Routine Description:
  654. Load repair text file (setup.log) into memory.
  655. Arguments:
  656. Filename - Supplies full filename (in NT namespace) of the file to
  657. be loaded.
  658. Handle - receives handle to loaded file, which can be
  659. used in subsequent calls to other text file services.
  660. Return Value:
  661. BOOLEAN value to indicate if the setup.log is processed.
  662. --*/
  663. {
  664. NTSTATUS Status;
  665. PWSTR Version;
  666. ULONG ErrorSubId;
  667. ULONG ErrorLine;
  668. //
  669. // Load setup.log
  670. //
  671. Status = SpLoadSetupTextFile(
  672. Filename,
  673. NULL, // No image already in memory
  674. 0, // Image size is empty
  675. Handle,
  676. &ErrorLine,
  677. TRUE,
  678. FALSE
  679. );
  680. if(!NT_SUCCESS(Status)) {
  681. if(Status == STATUS_UNSUCCESSFUL) {
  682. //
  683. // Syntax error in setup.log file
  684. //
  685. ErrorSubId = SP_TEXT_REPAIR_INF_ERROR_1;
  686. } else {
  687. //
  688. // Unable to load setup.log file
  689. //
  690. ErrorLine = 0;
  691. ErrorSubId = SP_TEXT_REPAIR_INF_ERROR_0;
  692. }
  693. SppRepairReportError(FALSE,
  694. SP_SCRN_REPAIR_INF_ERROR,
  695. ErrorSubId,
  696. NULL,
  697. ErrorLine,
  698. NULL );
  699. *Handle = NULL;
  700. return (FALSE);
  701. }
  702. //
  703. // Check if this setup.log file is for Winnt 3.5
  704. //
  705. Version = SpGetSectionKeyIndex(*Handle,
  706. SIF_NEW_REPAIR_SIGNATURE,
  707. SIF_NEW_REPAIR_VERSION_KEY,
  708. 0); // should be moved to spsif.c
  709. if(Version == NULL) {
  710. SppRepairReportError(FALSE,
  711. SP_SCRN_REPAIR_INF_ERROR,
  712. SP_TEXT_REPAIR_INF_ERROR_2,
  713. NULL,
  714. 0,
  715. NULL);
  716. } else {
  717. if(!_wcsicmp(Version,SIF_NEW_REPAIR_NT_VERSION)) {
  718. return(TRUE);
  719. } else {
  720. SppRepairReportError(FALSE,
  721. SP_SCRN_REPAIR_INF_ERROR,
  722. SP_TEXT_REPAIR_INF_ERROR_5,
  723. NULL,
  724. 0,
  725. NULL);
  726. }
  727. }
  728. //
  729. // Control comes here only when error occurs ...
  730. //
  731. SpFreeTextFile(*Handle);
  732. *Handle = NULL;
  733. return(FALSE);
  734. }
  735. VOID
  736. SpRepairDiskette(
  737. OUT PVOID *SifHandle,
  738. OUT PDISK_REGION *TargetRegion,
  739. OUT PWSTR *TargetPath,
  740. OUT PDISK_REGION *SystemPartitionRegion,
  741. OUT PWSTR *SystemPartitionDirectory
  742. )
  743. /*++
  744. Routine Description:
  745. This routine checks if there is a floppy drive. If no, it returns
  746. silently. Otherwise, it prompts user for Emergency Repair Disk.
  747. Arguments:
  748. SifHandle - Supplies a variable to receive the setup.log file handle.
  749. TargetRegion - Supplies a variable to receive the pointer to the target
  750. installation region.
  751. TargetPath - Supplies a variable to receive the nt name of target path.
  752. SystemPartitionRegion - Supplies a variable to receive the pointer of the
  753. system partition region.
  754. SystemPartitionDirectory - Supplies a variable to receive the osloader
  755. directory name on the system partition.
  756. Return Value:
  757. None.
  758. --*/
  759. {
  760. PWSTR szDiskName;
  761. BOOLEAN b, rc = FALSE;
  762. PWSTR FullLogFilename, p, FloppyDevicePath = L"\\device\\floppy0";
  763. PWSTR SystemPartition, WinntPartition;
  764. //
  765. // Assume failure.
  766. //
  767. *SifHandle = NULL;
  768. //
  769. // Always want to prompt for the disk in A:.
  770. // First, check if there is an A:. If no floppy drive,
  771. // simply skip the request for ER diskette.
  772. //
  773. if(SpGetFloppyDriveType(0) == FloppyTypeNone) {
  774. return;
  775. }
  776. //
  777. // Fetch the generic repair disk name.
  778. //
  779. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_TEXT_REPAIR_DISK_NAME);
  780. szDiskName = SpDupStringW(TemporaryBuffer);
  781. p = TemporaryBuffer;
  782. *p = 0;
  783. SpConcatenatePaths(p, FloppyDevicePath);
  784. SpConcatenatePaths(p, SETUP_LOG_FILENAME);
  785. FullLogFilename = SpDupStringW(p);
  786. while (rc == FALSE) {
  787. //
  788. // Prompt for the disk -- ignore what may be in the drive already,
  789. // and allow escape.
  790. //
  791. b = SpPromptForDisk(
  792. szDiskName,
  793. FloppyDevicePath,
  794. SETUP_LOG_FILENAME,
  795. TRUE, // Always prompt for at least once
  796. TRUE, // Allow user to cancel
  797. FALSE, // No multiple prompts
  798. NULL // don't care about redraw flag
  799. );
  800. //
  801. // If the user pressed escape at the disk prompt, bail out now.
  802. //
  803. if(!b) {
  804. rc = TRUE; // User canceled. Skip repair floppy
  805. } else {
  806. rc = SpLoadRepairLogFile(FullLogFilename, SifHandle);
  807. if (rc) {
  808. //
  809. // Now we need to figure out the partition, path information
  810. // to update boot.ini.
  811. //
  812. SppGetRepairPathInformation(*SifHandle,
  813. &SystemPartition,
  814. SystemPartitionDirectory,
  815. &WinntPartition,
  816. TargetPath
  817. );
  818. *SystemPartitionRegion = SpRegionFromNtName(
  819. SystemPartition,
  820. PartitionOrdinalCurrent);
  821. if (*SystemPartitionRegion == NULL) {
  822. SpFatalSifError(*SifHandle,
  823. SIF_NEW_REPAIR_PATHS,
  824. SIF_NEW_REPAIR_PATHS_SYSTEM_PARTITION_DEVICE,0,0);
  825. }
  826. *TargetRegion = SpRegionFromNtName(WinntPartition, PartitionOrdinalCurrent);
  827. if (*TargetRegion == NULL) {
  828. SpFatalSifError(*SifHandle,
  829. SIF_NEW_REPAIR_PATHS,
  830. SIF_NEW_REPAIR_PATHS_TARGET_DEVICE,0,0);
  831. }
  832. }
  833. }
  834. }
  835. SpMemFree(szDiskName);
  836. SpMemFree(FullLogFilename);
  837. return;
  838. }
  839. VOID
  840. SppRepairWinntFiles(
  841. IN PVOID LogFileHandle,
  842. IN PVOID MasterSifHandle,
  843. IN PWSTR SourceDevicePath,
  844. IN PWSTR DirectoryOnSourceDevice,
  845. IN PWSTR SystemPartition,
  846. IN PWSTR SystemPartitionDirectory,
  847. IN PWSTR WinntPartition,
  848. IN PWSTR WinntPartitionDirectory
  849. )
  850. /*++
  851. Routine Description:
  852. This routine goes through the system partition files and winnt files
  853. listed in the setup.log file and checks their validity.
  854. Arguments:
  855. LogFileHandle - Handle of the setup.log
  856. MasterSifHandle - Handle of the txtsetup.sif
  857. SourceDevicePath - supplies the NT name of the source device
  858. DirectoryOnSourceDevice - supplies the directory on the source device
  859. which contains source file.
  860. Return Value:
  861. None.
  862. --*/
  863. {
  864. PWSTR SystemPartitionFiles = L"system partition files";
  865. PWSTR WinntFiles = L"WinNt files";
  866. ULONG TotalFileCount;
  867. BOOLEAN RepairWithoutConfirming;
  868. //
  869. // Create file repair gauge
  870. //
  871. TotalFileCount = SpCountLinesInSection(LogFileHandle,SIF_NEW_REPAIR_SYSPARTFILES);
  872. TotalFileCount += SpCountLinesInSection(LogFileHandle,SIF_NEW_REPAIR_WINNTFILES);
  873. TotalFileCount += SpCountLinesInSection(LogFileHandle,SIF_NEW_REPAIR_FILES_IN_REPAIR_DIR);
  874. CLEAR_CLIENT_SCREEN();
  875. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_TEXT_SETUP_IS_EXAMINING);
  876. RepairGauge = SpCreateAndDisplayGauge(TotalFileCount,0,15,TemporaryBuffer,NULL,GF_PERCENTAGE,0);
  877. ASSERT(RepairGauge);
  878. //
  879. // delay opening of driver inf and cab file till required
  880. //
  881. ghSif = MasterSifHandle;
  882. gszDrvInfDeviceName = SourceDevicePath;
  883. gszDrvInfDirName = DirectoryOnSourceDevice;
  884. SpDisplayStatusText(SP_STAT_PLEASE_WAIT,DEFAULT_STATUS_ATTRIBUTE);
  885. SppRepairScreenRepaint(NULL, NULL, TRUE);
  886. //
  887. // first recreate all of the directories we copy into
  888. //
  889. if (SystemPartition != NULL) {
  890. SpCreateDirectory(SystemPartition,NULL,SystemPartitionDirectory,0,0);
  891. }
  892. //
  893. // Create the nt tree.
  894. //
  895. SpCreateDirectoryStructureFromSif(MasterSifHandle,
  896. SIF_NTDIRECTORIES,
  897. WinntPartition,
  898. WinntPartitionDirectory);
  899. //
  900. // Verify and repair the files in [Files.InRepairDirectory]. If textmode
  901. // setup is executing a disaster recovery, do not prompt the user for the
  902. // files to repair. Just go ahead and repair 'em.
  903. //
  904. RepairWithoutConfirming = SpDrEnabled() && SpDrIsRepairFast();
  905. SppVerifyAndRepairVdmFiles(LogFileHandle,
  906. WinntPartition,
  907. NULL,
  908. &RepairWithoutConfirming);
  909. //
  910. // Verify and repair the files in [FIles.SystemPartition]
  911. //
  912. SppVerifyAndRepairFiles(LogFileHandle,
  913. MasterSifHandle,
  914. SIF_NEW_REPAIR_SYSPARTFILES,
  915. SourceDevicePath,
  916. DirectoryOnSourceDevice,
  917. SystemPartition,
  918. SystemPartitionDirectory,
  919. TRUE,
  920. &RepairWithoutConfirming);
  921. //
  922. // Verify and repair the files in [Files.WinNt]
  923. //
  924. SppVerifyAndRepairFiles(LogFileHandle,
  925. MasterSifHandle,
  926. SIF_NEW_REPAIR_WINNTFILES,
  927. SourceDevicePath,
  928. DirectoryOnSourceDevice,
  929. WinntPartition,
  930. NULL,
  931. FALSE,
  932. &RepairWithoutConfirming);
  933. SpDestroyGauge(RepairGauge);
  934. RepairGauge = NULL;
  935. }
  936. VOID
  937. SppVerifyAndRepairFiles(
  938. IN PVOID LogFileHandle,
  939. IN PVOID MasterSifHandle,
  940. IN PWSTR SectionName,
  941. IN PWSTR SourceDevicePath,
  942. IN PWSTR DirectoryOnSourceDevice,
  943. IN PWSTR TargetDevicePath,
  944. IN PWSTR DirectoryOnTargetDevice,
  945. IN BOOLEAN SystemPartitionFiles,
  946. IN OUT PBOOLEAN RepairWithoutConfirming
  947. )
  948. /*++
  949. Routine Description:
  950. This routine goes through the files listed in the specified section of
  951. setup.log file and checks their validity. If a file's checksum does
  952. not match the checksum listed in the setup.log file, we will prompt
  953. the user and recopy the file from original installation sources.
  954. Arguments:
  955. LogFileHandle - Handle of the setup.log
  956. MasterSifHandle - Handle of the txtsetup.sif
  957. SectionName - Section in setup.log to be examined
  958. SourceDevicePath - supplies the NT name of the source device
  959. DirectoryOnSourceDevice - supplies the directory on the source device
  960. which contains source file.
  961. TargetDevicePath - supplies the nt name of the target device
  962. DirectoryOnTargetDevice - the name of the winnt directory on target
  963. device
  964. SystemPartitionFile - supplies a boolean value to indicate if the target
  965. file is on system partition
  966. RepairWithoutConfirming - Pointer to a flag that indicates whether or not
  967. setup should repair a damaged file without
  968. asking the user to confirm.
  969. Return Value:
  970. None.
  971. --*/
  972. {
  973. PWSTR FullTargetName, ChecksumString;
  974. PWSTR TargetDirectory, TargetFileName;
  975. PWSTR SourceFileName;
  976. ULONG Checksum, FileChecksum, PrefixLength, Length, Count, i;
  977. BOOLEAN IsNtImage, IsValid, RepairFile, SysPartNTFS = FALSE;
  978. BOOLEAN RedrawGauge = TRUE, ForceNoComp;
  979. FILE_TO_COPY FileToCopy;
  980. PWSTR OemDiskDescription, OemDiskTag, OemSourceDirectory;
  981. PWSTR DevicePath, Directory, q;
  982. PWSTR MediaShortName, PreviousMediaName = L"";
  983. PWSTR MediaDir;
  984. NTSTATUS Status;
  985. //
  986. // Allocate a SMALL buffer for local use and init FileToCopy struct
  987. //
  988. TargetDirectory = NULL;
  989. FullTargetName = SpMemAlloc(1024);
  990. *FullTargetName = 0;
  991. FileToCopy.Next = NULL;
  992. FileToCopy.AbsoluteTargetDirectory = TRUE;
  993. FileToCopy.TargetDevicePath = TargetDevicePath;
  994. SpConcatenatePaths(FullTargetName,TargetDevicePath);
  995. if(SystemPartitionFiles) {
  996. PDISK_REGION SystemPartitionRegion;
  997. //
  998. // We must find out whether the system partition is NTFS, because
  999. // if it is, then we might want to make sure it's not compressed.
  1000. //
  1001. if(SystemPartitionRegion = SpRegionFromNtName(TargetDevicePath,
  1002. PartitionOrdinalCurrent)) {
  1003. SysPartNTFS = (SystemPartitionRegion->Filesystem == FilesystemNtfs);
  1004. }
  1005. //
  1006. // For system partition files, we need to concatenate target
  1007. // directory to FullTargetName. Because the target filename
  1008. // of system partition files do not have target directory.
  1009. //
  1010. FileToCopy.TargetDirectory = DirectoryOnTargetDevice;
  1011. SpConcatenatePaths(FullTargetName,FileToCopy.TargetDirectory);
  1012. }
  1013. PrefixLength = wcslen(FullTargetName);
  1014. Count = SpCountLinesInSection(LogFileHandle,SectionName);
  1015. for (i = 0; i < Count; i++) {
  1016. if (RedrawGauge) {
  1017. SppRepairScreenRepaint(NULL, NULL, TRUE);
  1018. RedrawGauge = FALSE;
  1019. }
  1020. SpTickGauge(RepairGauge);
  1021. //
  1022. // Initialize the 'ForceNoComp' flag to FALSE, thus allowing the
  1023. // file to use NTFS compression.
  1024. //
  1025. ForceNoComp = FALSE;
  1026. //
  1027. // Initialize target fullname to be DevicePath+Directory for
  1028. // system partition file or DevicePath for Winnt files
  1029. //
  1030. FullTargetName[PrefixLength] = (WCHAR)NULL;
  1031. //
  1032. // If we allocate space for TargetDirectory we must free it.
  1033. //
  1034. if (TargetDirectory) {
  1035. SpMemFree(TargetDirectory);
  1036. TargetDirectory = NULL;
  1037. }
  1038. TargetFileName = SpGetKeyName(LogFileHandle,SectionName,i);
  1039. if(!TargetFileName) {
  1040. SppRepairReportError(FALSE,
  1041. SP_SCRN_REPAIR_INF_ERROR_0,
  1042. SP_TEXT_REPAIR_INF_ERROR_1,
  1043. SectionName,
  1044. i,
  1045. NULL);
  1046. RedrawGauge = TRUE;
  1047. continue;
  1048. }
  1049. //
  1050. // If the target file name contains \system32\config\, it is
  1051. // hive related file. We simply ignore it.
  1052. //
  1053. q = SpDupStringW(TargetFileName);
  1054. SpStringToUpper(q);
  1055. if (wcsstr(q,L"\\SYSTEM32\\CONFIG\\")) {
  1056. SpMemFree(q);
  1057. continue;
  1058. }
  1059. SpMemFree(q);
  1060. SpConcatenatePaths(FullTargetName,TargetFileName);
  1061. SpDisplayStatusText(SP_STAT_EXAMINING_WINNT,
  1062. DEFAULT_STATUS_ATTRIBUTE,
  1063. TargetFileName);
  1064. ChecksumString = SpGetSectionLineIndex(LogFileHandle,SectionName,i,1);
  1065. if(!ChecksumString) {
  1066. SppRepairReportError(FALSE,
  1067. SP_SCRN_REPAIR_INF_ERROR_0,
  1068. SP_TEXT_REPAIR_INF_ERROR_1,
  1069. SectionName,
  1070. i,
  1071. NULL);
  1072. RedrawGauge = TRUE;
  1073. continue;
  1074. }
  1075. Checksum = (ULONG)SpStringToLong(ChecksumString, NULL, 16);
  1076. //
  1077. // Validate the security set on the file.
  1078. // Note that we do not check the files in the system partition
  1079. // on non-x86 systems since it is always FAT
  1080. //
  1081. #if !defined(_AMD64_) && !defined(_X86_)
  1082. if(!SystemPartitionFiles) {
  1083. #endif // !defined(_AMD64_) && !defined(_X86_)
  1084. Status = SpVerifyFileAccess( FullTargetName,
  1085. STANDARD_RIGHTS_READ |
  1086. FILE_READ_ATTRIBUTES |
  1087. FILE_WRITE_ATTRIBUTES |
  1088. DELETE |
  1089. WRITE_DAC |
  1090. SYNCHRONIZE );
  1091. if( !NT_SUCCESS( Status ) &&
  1092. ((Status == STATUS_ACCESS_DENIED)||(Status == STATUS_PRIVILEGE_NOT_HELD)) ) {
  1093. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Security of %ls, must be fixed. Status = %x\n", FullTargetName, Status ));
  1094. Status = SpSetDefaultFileSecurity( FullTargetName );
  1095. if( !NT_SUCCESS( Status ) ) {
  1096. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to change security of %ls. Status = %x\n", FullTargetName, Status ));
  1097. }
  1098. }
  1099. #if !defined(_AMD64_) && !defined(_X86_)
  1100. }
  1101. #endif // !defined(_AMD64_) && !defined(_X86_)
  1102. //
  1103. // If this is a system partition file and the system partition is NTFS,
  1104. // then check to see whether this file can use NTFS compression, and
  1105. // if not, force it to be uncompressed.
  1106. //
  1107. if((SysPartNTFS) &&
  1108. IsFileFlagSet(MasterSifHandle,TargetFileName,FILEFLG_FORCENOCOMP))
  1109. {
  1110. ForceNoComp = TRUE;
  1111. SpVerifyNoCompression(FullTargetName);
  1112. }
  1113. SpValidateAndChecksumFile(NULL,FullTargetName,&IsNtImage,&FileChecksum,&IsValid);
  1114. //
  1115. // If the image is invalid or the file on the target is not the
  1116. // original file copied by setup, we will recopy it.
  1117. //
  1118. if (!IsValid || FileChecksum != Checksum) {
  1119. //
  1120. // Ask user if he wants to repair the file
  1121. //
  1122. if(*RepairWithoutConfirming) {
  1123. RepairFile = TRUE;
  1124. } else {
  1125. RepairFile = SppRepairReportError(
  1126. TRUE,
  1127. SP_SCRN_REPAIR_FILE_MISMATCH,
  1128. SP_TEXT_REPAIR_INF_ERROR_4,
  1129. TargetFileName,
  1130. i,
  1131. RepairWithoutConfirming);
  1132. RedrawGauge = TRUE;
  1133. }
  1134. if (!RepairFile) {
  1135. continue;
  1136. }
  1137. SpDisplayStatusText(SP_STAT_REPAIR_WINNT,
  1138. DEFAULT_STATUS_ATTRIBUTE,
  1139. TargetFileName);
  1140. if (SystemPartitionFiles) {
  1141. FileToCopy.TargetFilename = TargetFileName;
  1142. } else {
  1143. //
  1144. // For Winnt files, the TargetName contains path and filename.
  1145. // We need to seperate them.
  1146. //
  1147. TargetDirectory = SpDupStringW(TargetFileName);
  1148. Length = wcslen(TargetDirectory);
  1149. while (Length) {
  1150. if (TargetDirectory[Length] == L'\\') {
  1151. TargetDirectory[Length] = 0;
  1152. TargetFileName = &TargetDirectory[Length + 1];
  1153. break;
  1154. } else {
  1155. Length--;
  1156. }
  1157. }
  1158. if (Length == 0) {
  1159. SppRepairReportError(FALSE,
  1160. SP_SCRN_REPAIR_INF_ERROR_0,
  1161. SP_TEXT_REPAIR_INF_ERROR_1,
  1162. SectionName,
  1163. i,
  1164. NULL);
  1165. RedrawGauge = TRUE;
  1166. continue;
  1167. }
  1168. FileToCopy.TargetFilename = TargetFileName;
  1169. FileToCopy.TargetDirectory = TargetDirectory;
  1170. }
  1171. SourceFileName = SpGetSectionLineIndex(LogFileHandle,SectionName,i,0);
  1172. if (!SourceFileName) {
  1173. SppRepairReportError(FALSE,
  1174. SP_SCRN_REPAIR_INF_ERROR_0,
  1175. SP_TEXT_REPAIR_INF_ERROR_1,
  1176. SectionName,
  1177. i,
  1178. NULL);
  1179. RedrawGauge = TRUE;
  1180. continue;
  1181. }
  1182. FileToCopy.SourceFilename = NULL;
  1183. q = SpDupStringW(SourceFileName);
  1184. SpStringToUpper(q);
  1185. if (wcsstr(q,L"DRIVER.CAB")) {
  1186. SpMemFree(q);
  1187. q = SpDupStringW(TargetFileName);
  1188. SpStringToUpper(q);
  1189. if (!wcsstr(q,L"DRIVER.CAB")) {
  1190. FileToCopy.SourceFilename = TargetFileName;
  1191. }
  1192. }
  1193. SpMemFree(q);
  1194. FileToCopy.SourceFilename = FileToCopy.SourceFilename
  1195. ? FileToCopy.SourceFilename
  1196. : SourceFileName;
  1197. FileToCopy.Flags = COPY_ALWAYS | COPY_NOVERSIONCHECK | (ForceNoComp ? COPY_FORCENOCOMP : 0);
  1198. //
  1199. // The file may come from OEM diskette. We need to check if the
  1200. // sources device is listed in log file. If not, it must be
  1201. // from MS setup sources.
  1202. //
  1203. OemSourceDirectory = SpGetSectionLineIndex(LogFileHandle,SectionName,i,2);
  1204. OemDiskTag = NULL;
  1205. if (OemSourceDirectory) {
  1206. OemDiskDescription = SpGetSectionLineIndex(LogFileHandle,SectionName,i,3);
  1207. if (OemDiskDescription) {
  1208. OemDiskTag = SpGetSectionLineIndex(LogFileHandle,SectionName,i,4);
  1209. if((OemDiskTag != NULL) &&
  1210. (wcslen(OemDiskTag) == 0)){
  1211. OemDiskTag = SourceFileName;
  1212. }
  1213. }
  1214. }
  1215. if (OemDiskTag) {
  1216. BOOLEAN rs;
  1217. PWSTR szDevicePath = SpDupStringW(L"\\device\\floppy0");
  1218. //
  1219. // Prompt for the disk, based on the setup media type.
  1220. //
  1221. rs = SpPromptForDisk(
  1222. OemDiskDescription,
  1223. szDevicePath,
  1224. OemDiskTag,
  1225. FALSE, // don't ignore disk in drive
  1226. TRUE, // allow escape
  1227. TRUE, // warn about multiple prompts for same disk
  1228. NULL // don't care redraw flag
  1229. );
  1230. SpMemFree(szDevicePath);
  1231. RedrawGauge = TRUE;
  1232. if (rs == FALSE) {
  1233. continue;
  1234. }
  1235. DevicePath = L"\\device\\floppy0";
  1236. Directory = OemSourceDirectory;
  1237. MediaDir = NULL;
  1238. } else {
  1239. PWSTR szDescription = 0, szTagFileName = 0;
  1240. BOOLEAN bDiskFound = FALSE;
  1241. //
  1242. // Search SourceFileName against txtsetup.sif to figure out its
  1243. // media name.
  1244. //
  1245. MediaShortName = SpLookUpValueForFile(
  1246. MasterSifHandle,
  1247. SourceFileName,
  1248. INDEX_WHICHMEDIA,
  1249. FALSE
  1250. );
  1251. if(MediaShortName) {
  1252. SpGetSourceMediaInfo(MasterSifHandle,MediaShortName,NULL,NULL,&MediaDir);
  1253. } else {
  1254. SpNonFatalSifError(
  1255. MasterSifHandle,
  1256. SIF_FILESONSETUPMEDIA,
  1257. SourceFileName,
  1258. 0,
  1259. INDEX_WHICHMEDIA,
  1260. SourceFileName
  1261. );
  1262. //
  1263. // If we returned from SpNonFatalSifError, then the user wants to
  1264. // skip the file.
  1265. //
  1266. RedrawGauge = TRUE;
  1267. continue;
  1268. }
  1269. //
  1270. // Prompt user to insert the source media, if changed.
  1271. //
  1272. SpGetSourceMediaInfo(MasterSifHandle, MediaShortName,
  1273. &szDescription, &szTagFileName, NULL);
  1274. //
  1275. // Prompt for the disk, based on the setup media type.
  1276. //
  1277. bDiskFound = SpPromptForDisk(
  1278. szDescription,
  1279. SourceDevicePath,
  1280. szTagFileName,
  1281. FALSE, // don't ignore disk in drive
  1282. TRUE, // don't allow escape
  1283. TRUE, // warn about multiple prompts for same disk
  1284. NULL // don't care redraw flag
  1285. );
  1286. RedrawGauge = TRUE;
  1287. //
  1288. // user might have wanted to skip the file
  1289. //
  1290. if (!bDiskFound)
  1291. continue;
  1292. DevicePath = SourceDevicePath;
  1293. Directory = DirectoryOnSourceDevice;
  1294. }
  1295. //
  1296. // Copy the file.
  1297. //
  1298. // If the file is listed for lock smashing then we need to smash it
  1299. // if installing UP on x86 (we don't bother with the latter
  1300. // qualifications here).
  1301. //
  1302. SpCopyFileWithRetry(
  1303. &FileToCopy,
  1304. DevicePath,
  1305. Directory,
  1306. MediaDir,
  1307. NULL, // TargetRoot -> NULL
  1308. SystemPartitionFiles ? FILE_ATTRIBUTES_RHS : 0,
  1309. SppRepairScreenRepaint,
  1310. NULL, // Do not want checksum
  1311. NULL, // Do not want to know if file was skipped
  1312. IsFileFlagSet(
  1313. MasterSifHandle,
  1314. FileToCopy.TargetFilename,
  1315. FILEFLG_SMASHLOCKS) ? COPY_SMASHLOCKS : 0
  1316. );
  1317. }
  1318. }
  1319. SpMemFree(FullTargetName);
  1320. if (RedrawGauge) {
  1321. SppRepairScreenRepaint(NULL, NULL, TRUE);
  1322. }
  1323. }
  1324. BOOLEAN
  1325. SpDisplayRepairMenu(
  1326. VOID
  1327. )
  1328. /*++
  1329. Routine Description:
  1330. This routine presents a list of repairable items to user and
  1331. let user choose the items to be fixed among the list.
  1332. Arguments:
  1333. None.
  1334. Return Value:
  1335. None. Some global repare variables are set or cleared.
  1336. --*/
  1337. {
  1338. PVOID Menu;
  1339. ULONG MenuTopY;
  1340. ULONG ValidKeys[] = { KEY_F3, ASCI_CR, ASCI_ESC, 0 };
  1341. ULONG Keypress, MessageIds[RepairItemMax];
  1342. ULONG i;
  1343. ULONG_PTR OptionChosen, InitialHighlight;
  1344. PWSTR MenuItem;
  1345. ULONG ListBoxWidth, curLBEntryWidth;
  1346. //
  1347. // Initialize repair options to repair ALL.
  1348. // Initialize repair menu item message id.
  1349. //
  1350. for (i = 0; i < RepairItemMax; i++) {
  1351. RepairItems[i] = 1;
  1352. if (i == 0) {
  1353. MessageIds[i] = SP_REPAIR_MENU_ITEM_1;
  1354. } else {
  1355. MessageIds[i] = MessageIds[i - 1] + 1;
  1356. }
  1357. }
  1358. while(1) {
  1359. //
  1360. // Display the text that goes above the menu on the partitioning screen.
  1361. //
  1362. SpDisplayScreen(SP_SCRN_REPAIR_MENU,3,CLIENT_TOP+1);
  1363. //
  1364. // Calculate menu placement. Leave one blank line
  1365. // and one line for a frame.
  1366. //
  1367. MenuTopY = NextMessageTopLine + (SplangQueryMinimizeExtraSpacing() ? 2 : 5);
  1368. //
  1369. // Create a menu.
  1370. // First, find the longest string, so we can size the listbox accordingly
  1371. //
  1372. ListBoxWidth = LIST_BOX_WIDTH; // It will be at least this wide
  1373. for (i = 0; i <= RepairItemMax; i++ ) {
  1374. if (i == RepairItemMax) {
  1375. SpFormatMessage(TemporaryBuffer,
  1376. sizeof(TemporaryBuffer),
  1377. SP_REPAIR_MENU_ITEM_CONTINUE);
  1378. } else {
  1379. #pragma prefast(suppress:201, "Logic takes care of the condition where buffer index refers beyond the buffer size")
  1380. SpFormatMessage(TemporaryBuffer,
  1381. sizeof(TemporaryBuffer),
  1382. MessageIds[i]);
  1383. }
  1384. if((curLBEntryWidth = SplangGetColumnCount(TemporaryBuffer)+(2*MENU_INDENT)) > ListBoxWidth) {
  1385. ListBoxWidth = min(curLBEntryWidth, MENU_WIDTH);
  1386. }
  1387. }
  1388. Menu = SpMnCreate(
  1389. MENU_LEFT_X,
  1390. MenuTopY,
  1391. ListBoxWidth,
  1392. LIST_BOX_HEIGHT
  1393. );
  1394. if( !Menu )
  1395. return FALSE;
  1396. ASSERT(Menu);
  1397. for (i = 0; i <= RepairItemMax; i++ ) {
  1398. if (i == RepairItemMax) {
  1399. SpFormatMessage(TemporaryBuffer,
  1400. sizeof(TemporaryBuffer),
  1401. SP_REPAIR_MENU_ITEM_CONTINUE);
  1402. } else {
  1403. #pragma prefast(suppress:201, "Logic takes care of the condition where buffer index refers beyond the buffer size")
  1404. SpFormatMessage(TemporaryBuffer,
  1405. sizeof(TemporaryBuffer),
  1406. MessageIds[i]);
  1407. (TemporaryBuffer)[1] = RepairItems[i] ? L'X' : L' ';
  1408. }
  1409. SpMnAddItem(Menu,
  1410. TemporaryBuffer,
  1411. MENU_LEFT_X+MENU_INDENT,
  1412. ListBoxWidth-(2*MENU_INDENT),
  1413. TRUE,
  1414. i
  1415. );
  1416. }
  1417. InitialHighlight = RepairItemMax;
  1418. //
  1419. // Initialize the status line.
  1420. //
  1421. SpDisplayStatusOptions(
  1422. DEFAULT_STATUS_ATTRIBUTE,
  1423. SP_STAT_F3_EQUALS_EXIT,
  1424. SP_STAT_ESC_EQUALS_CANCEL,
  1425. SP_STAT_ENTER_EQUALS_CHANGE,
  1426. 0
  1427. );
  1428. DisplayMenu:
  1429. //
  1430. // Display the menu
  1431. //
  1432. SpMnDisplay(
  1433. Menu,
  1434. InitialHighlight,
  1435. TRUE,
  1436. ValidKeys,
  1437. NULL,
  1438. NULL,
  1439. NULL,
  1440. &Keypress,
  1441. &OptionChosen
  1442. );
  1443. //
  1444. // Now act on the user's selection.
  1445. //
  1446. switch(Keypress) {
  1447. case KEY_F3:
  1448. SpConfirmExit();
  1449. break;
  1450. case ASCI_CR:
  1451. if (OptionChosen == RepairItemMax) {
  1452. SpMnDestroy(Menu);
  1453. return( TRUE );
  1454. } else {
  1455. MenuItem = SpMnGetText(Menu, OptionChosen);
  1456. if( !MenuItem )
  1457. goto DisplayMenu;
  1458. RepairItems[OptionChosen] ^= 1;
  1459. if (RepairItems[OptionChosen]) {
  1460. MenuItem[1] = L'X';
  1461. } else {
  1462. MenuItem[1] = L' ';
  1463. }
  1464. InitialHighlight = OptionChosen;
  1465. goto DisplayMenu;
  1466. }
  1467. break;
  1468. default:
  1469. SpMnDestroy(Menu);
  1470. return(FALSE);
  1471. }
  1472. SpMnDestroy(Menu);
  1473. }
  1474. }
  1475. NTSTATUS
  1476. SppRepairFile(
  1477. IN PVOID MasterSifHandle,
  1478. IN PWSTR TargetPath,
  1479. IN PWSTR TargetFilename,
  1480. IN PWSTR SourceDevicePath,
  1481. IN PWSTR DirectoryOnSourceDevice,
  1482. IN PWSTR SourceFilename,
  1483. IN BOOLEAN SystemPartitionFile
  1484. )
  1485. /*++
  1486. Routine Description:
  1487. This routine repairs ONE file and the source of the file MUST be on
  1488. emergency repair diskette or on the repair directory of the winnt
  1489. being repaired.
  1490. Arguments:
  1491. MasterSifHandle - Hanle of the txtsetup.sif
  1492. TargetPath - Supplies the target file path
  1493. TargetFilename - supplies the name of the target file
  1494. SourceDevicePath - supplies the NT name of the source device
  1495. DirectoryOnSourceDevice - supplies the directory on the source device
  1496. which contains source file.
  1497. SourceFilename - supplies the name of the source file
  1498. SystemPartitionFile - supplies a boolean value to indicate if the target
  1499. file is on system partition
  1500. Return Value:
  1501. NTSTATUS of the file copy.
  1502. --*/
  1503. {
  1504. PWSTR szDiskName;
  1505. PWSTR FullSourceFilename, FullTargetFilename;
  1506. NTSTATUS Status;
  1507. if (RepairFromErDisk) {
  1508. //
  1509. // Fetch the generic repair disk name.
  1510. //
  1511. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),
  1512. SP_TEXT_REPAIR_DISK_NAME);
  1513. szDiskName = SpDupStringW(TemporaryBuffer);
  1514. //
  1515. // Prompt for the disk -- do not ignore what may be in the drive
  1516. // already, and dont allow escape.
  1517. //
  1518. SpPromptForDisk(
  1519. szDiskName,
  1520. SourceDevicePath,
  1521. SETUP_LOG_FILENAME,
  1522. FALSE, // if disk is in already dont prompt
  1523. FALSE, // Do not allow user to cancel
  1524. TRUE, // warn for multiple prompts
  1525. NULL // don't care about redraw flag
  1526. );
  1527. SpMemFree(szDiskName);
  1528. }
  1529. //
  1530. // Form the name of the source and target fullname.
  1531. //
  1532. wcscpy(TemporaryBuffer, TargetPath);
  1533. SpConcatenatePaths(TemporaryBuffer, TargetFilename);
  1534. FullTargetFilename = SpDupStringW(TemporaryBuffer);
  1535. wcscpy(TemporaryBuffer, SourceDevicePath);
  1536. SpConcatenatePaths(TemporaryBuffer, DirectoryOnSourceDevice);
  1537. SpConcatenatePaths(TemporaryBuffer, SourceFilename);
  1538. FullSourceFilename = SpDupStringW(TemporaryBuffer);
  1539. //
  1540. // Copy the file.
  1541. //
  1542. // If the file is listed for lock smashing then we need to smash it
  1543. // if installing UP on x86 (we don't bother with the latter
  1544. // qualifications here).
  1545. //
  1546. Status = SpCopyFileUsingNames(
  1547. FullSourceFilename,
  1548. FullTargetFilename,
  1549. SystemPartitionFile ? FILE_ATTRIBUTES_RHS : 0,
  1550. IsFileFlagSet(MasterSifHandle,TargetFilename,FILEFLG_SMASHLOCKS) ? COPY_SMASHLOCKS : 0
  1551. );
  1552. SpMemFree(FullSourceFilename);
  1553. SpMemFree(FullTargetFilename);
  1554. return(Status);
  1555. }
  1556. VOID
  1557. SppRepairStartMenuGroupsAndItems(
  1558. IN PWSTR WinntPartition,
  1559. IN PWSTR WinntDirectory
  1560. )
  1561. /*++
  1562. Routine Description:
  1563. This routine loads the software hive, and set a value on Winlogon key
  1564. to indicate to Winlogon that it should recreate the Start Menu groups
  1565. and items for the Default User.
  1566. Arguments:
  1567. WinntPartition - supplies the NT name of the Winnt partition.
  1568. WinntDirectory - Supplies the name of the Winnt directory.
  1569. Return Value:
  1570. None.
  1571. --*/
  1572. {
  1573. NTSTATUS Status;
  1574. PWSTR p,q;
  1575. PWSTR LOCAL_MACHINE_KEY_NAME = L"\\registry\\machine";
  1576. ULONG Repair = 1;
  1577. PWSTR WINLOGON_KEY_NAME = L"Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
  1578. PWSTR REPAIR_VALUE_NAME = L"Repair";
  1579. OBJECT_ATTRIBUTES Obja;
  1580. UNICODE_STRING UnicodeString;
  1581. HANDLE SoftwareKey;
  1582. //
  1583. // Put up a screen telling the user what we are doing.
  1584. //
  1585. // SpStartScreen(SP_SCRN_REPAIR_CHECK_HIVES,
  1586. // 0,
  1587. // 8,
  1588. // TRUE,
  1589. // FALSE,
  1590. // DEFAULT_ATTRIBUTE
  1591. // );
  1592. //
  1593. // SpDisplayStatusText(SP_STAT_REG_LOADING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
  1594. //
  1595. // Load the software hive
  1596. //
  1597. //
  1598. // Form the name of the hive file.
  1599. // This is WinntPartition + WinntDirectory + system32\config + the hive name.
  1600. //
  1601. p = NULL;
  1602. q = NULL;
  1603. wcscpy(TemporaryBuffer,WinntPartition);
  1604. SpConcatenatePaths(TemporaryBuffer,WinntDirectory);
  1605. SpConcatenatePaths(TemporaryBuffer,L"system32\\config\\software");
  1606. p = SpDupStringW( TemporaryBuffer );
  1607. //
  1608. // Form the path of the key into which we will
  1609. // load the hive. We'll use the convention that
  1610. // a hive will be loaded into \registry\machine\x<hivename>.
  1611. //
  1612. wcscpy(TemporaryBuffer,LOCAL_MACHINE_KEY_NAME);
  1613. SpConcatenatePaths(TemporaryBuffer,L"x");
  1614. wcscat(TemporaryBuffer,L"software");
  1615. q = SpDupStringW( TemporaryBuffer );
  1616. if( (p == NULL) || (q == NULL) ) {
  1617. goto fix_strtmenu_cleanup_1;
  1618. }
  1619. //
  1620. // Attempt to load the hive.
  1621. //
  1622. Status = SpLoadUnloadKey(NULL,NULL,q,p);
  1623. if(!NT_SUCCESS(Status)) {
  1624. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to load hive %ws to key %ws (%lx)\n",p,q,Status));
  1625. goto fix_strtmenu_cleanup_1;
  1626. }
  1627. INIT_OBJA(&Obja,&UnicodeString,q);
  1628. Status = ZwOpenKey(&SoftwareKey,KEY_ALL_ACCESS,&Obja);
  1629. if(!NT_SUCCESS(Status)) {
  1630. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ws (%lx)\n",q,Status));
  1631. goto fix_strtmenu_cleanup_2;
  1632. }
  1633. Status = SpOpenSetValueAndClose(
  1634. SoftwareKey,
  1635. WINLOGON_KEY_NAME,
  1636. REPAIR_VALUE_NAME,
  1637. REG_DWORD,
  1638. &Repair,
  1639. sizeof(ULONG)
  1640. );
  1641. if(!NT_SUCCESS(Status)) {
  1642. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set value %ws on key %ws. Status = %lx\n",REPAIR_VALUE_NAME,REPAIR_VALUE_NAME,Status));
  1643. goto fix_strtmenu_cleanup_3;
  1644. }
  1645. Status = ZwFlushKey(SoftwareKey );
  1646. fix_strtmenu_cleanup_3:
  1647. Status = ZwClose( SoftwareKey );
  1648. fix_strtmenu_cleanup_2:
  1649. Status = SpLoadUnloadKey(NULL,NULL,q,NULL);
  1650. fix_strtmenu_cleanup_1:
  1651. if( p != NULL ) {
  1652. SpMemFree( p );
  1653. }
  1654. if( q != NULL ) {
  1655. SpMemFree( q );
  1656. }
  1657. }
  1658. VOID
  1659. SppInspectHives(
  1660. IN PWSTR PartitionPath,
  1661. IN PWSTR SystemRoot,
  1662. OUT PULONG HiveLoaded,
  1663. IN PWSTR *HiveNames
  1664. )
  1665. /*++
  1666. Routine Description:
  1667. This routine inspects setup hives by loading and unloading them and
  1668. returns the loadable information in HiveLoaded[].
  1669. Arguments:
  1670. PartitionPath - supplies the NT name of the Winnt partition.
  1671. SystemRoot - Supplies the name of the Winnt System root.
  1672. HiveLoaded - Supplies a pointer to a ULONG array to receive the
  1673. loadable information for each hive inspected.
  1674. HIveNames - Supplies a pointer to a PWSTR array to receive the
  1675. name of hives to inspect.
  1676. Return Value:
  1677. None. HiveLoaded array initialized.
  1678. --*/
  1679. {
  1680. NTSTATUS Status;
  1681. PWSTR pwstrTemp1,pwstrTemp2;
  1682. int h;
  1683. PWSTR LOCAL_MACHINE_KEY_NAME = L"\\registry\\machine";
  1684. //
  1685. // Put up a screen telling the user what we are doing.
  1686. //
  1687. SpStartScreen(SP_SCRN_REPAIR_CHECK_HIVES,
  1688. 0,
  1689. 8,
  1690. TRUE,
  1691. FALSE,
  1692. DEFAULT_ATTRIBUTE
  1693. );
  1694. SpDisplayStatusText(SP_STAT_REG_LOADING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
  1695. //
  1696. // Load each template hive we care about from the target tree.
  1697. //
  1698. for (h = 0; h < RepairHiveMax; h++) {
  1699. pwstrTemp1 = TemporaryBuffer;
  1700. pwstrTemp2 = TemporaryBuffer + (sizeof(TemporaryBuffer) / sizeof(WCHAR) / 2);
  1701. if( h != RepairHiveUser ) {
  1702. //
  1703. // Form the name of the hive file.
  1704. // This is partitionpath + sysroot + system32\config + the hive name.
  1705. //
  1706. wcscpy(pwstrTemp1,PartitionPath);
  1707. SpConcatenatePaths(pwstrTemp1,SystemRoot);
  1708. SpConcatenatePaths(pwstrTemp1,L"system32\\config");
  1709. SpConcatenatePaths(pwstrTemp1,HiveNames[h]);
  1710. } else {
  1711. wcscpy(pwstrTemp1,PartitionPath);
  1712. SpConcatenatePaths(pwstrTemp1,DEFAULT_USER_PATH);
  1713. SpConcatenatePaths(pwstrTemp1,HiveNames[h]);
  1714. }
  1715. //
  1716. // First we must verify that the hive file exists. We have to do
  1717. // this because loading a hive will create one if it didn't already
  1718. // exist!
  1719. //
  1720. if(!SpFileExists(pwstrTemp1, FALSE)) {
  1721. HiveLoaded[h] = 0;
  1722. continue;
  1723. }
  1724. //
  1725. // Form the path of the key into which we will
  1726. // load the hive. We'll use the convention that
  1727. // a hive will be loaded into \registry\machine\x<hivename>.
  1728. //
  1729. wcscpy(pwstrTemp2,LOCAL_MACHINE_KEY_NAME);
  1730. SpConcatenatePaths(pwstrTemp2,L"x");
  1731. wcscat(pwstrTemp2,HiveNames[h]);
  1732. //
  1733. // Attempt to load the hive.
  1734. //
  1735. HiveLoaded[h] = 0;
  1736. Status = SpLoadUnloadKey(NULL,NULL,pwstrTemp2,pwstrTemp1);
  1737. if (NT_SUCCESS(Status) || Status == STATUS_NO_MEMORY) {
  1738. //
  1739. // If the reason the hive did not load is because of not
  1740. // enough memory. We assume the hive is OK.
  1741. //
  1742. HiveLoaded[h] = 1;
  1743. //
  1744. // Unload the hive.
  1745. //
  1746. SpLoadUnloadKey(NULL,NULL,pwstrTemp2,NULL);
  1747. }
  1748. }
  1749. //
  1750. // Sam and security hives must be updated together. If any one of
  1751. // them failed to load, we must update both.
  1752. //
  1753. if ((HiveLoaded[RepairHiveSecurity] == 0) ||
  1754. (HiveLoaded[RepairHiveSam] == 0)) {
  1755. HiveLoaded[RepairHiveSam] = 0;
  1756. HiveLoaded[RepairHiveSecurity] = 0;
  1757. }
  1758. }
  1759. VOID
  1760. SppRepairHives(
  1761. PVOID MasterSifHandle,
  1762. PWSTR WinntPartition,
  1763. PWSTR WinntPartitionDirectory,
  1764. PWSTR SourceDevicePath,
  1765. PWSTR DirectoryOnSourceDevice
  1766. )
  1767. /*++
  1768. Routine Description:
  1769. This routine inspects hives and let user choose the hives which he
  1770. wants to repair.
  1771. Arguments:
  1772. MasterSifHandle - The handle of textsetup.sif
  1773. WinntPartition - The nt name of Winnt partition
  1774. WinntPartitionDirectory - The directory name of winnt installation
  1775. SourceDevicePath - The NT name of source device which contains hives
  1776. DirectoryOnSourceDevice - The directory name of source device
  1777. Return Value:
  1778. None.
  1779. --*/
  1780. {
  1781. //
  1782. // Do not change the order of the files in 'HiveNames' array.
  1783. // If you do that, you also need to change the order of the
  1784. // enum 'RepairHive' in spntfix.h
  1785. //
  1786. PWSTR HiveNames[RepairHiveMax] = { L"system",L"software",L"default",L"ntuser.dat",L"security",L"sam"};
  1787. ULONG HiveLoaded[RepairHiveMax];
  1788. PVOID Menu;
  1789. ULONG MenuTopY;
  1790. ULONG ValidKeys[] = { KEY_F3, ASCI_CR, 0 };
  1791. ULONG ValidKeys1[] = { KEY_F3, ASCI_CR, 0 };
  1792. ULONG i;
  1793. ULONG_PTR InitialHighlight, OptionChosen;
  1794. PWSTR MenuItem, TargetPath, p;
  1795. ULONG Keypress, MessageIds[RepairHiveMax];
  1796. BOOLEAN Selectable;
  1797. NTSTATUS Status;
  1798. ULONG ListBoxWidth, curLBEntryWidth;
  1799. BOOLEAN DetermineHivesToRepair;
  1800. //
  1801. // Inspect hives by loading hives to determine which hives need to be
  1802. // fixed.
  1803. //
  1804. SppInspectHives(WinntPartition,
  1805. WinntPartitionDirectory,
  1806. HiveLoaded,
  1807. HiveNames);
  1808. // BCL - Seagate: If doing ASR, don't do the menu.
  1809. if ( SpDrEnabled() ) {
  1810. goto UpdateTheHives;
  1811. }
  1812. //
  1813. // Initialize hive menu item message id.
  1814. //
  1815. for (i = 0; i < RepairHiveMax; i++) {
  1816. if (i == 0) {
  1817. MessageIds[i] = SP_REPAIR_HIVE_ITEM_1;
  1818. } else {
  1819. MessageIds[i] = MessageIds[i - 1] + 1;
  1820. }
  1821. }
  1822. DetermineHivesToRepair = TRUE;
  1823. while(DetermineHivesToRepair) {
  1824. //
  1825. // Display the text that goes above the menu on the partitioning screen.
  1826. //
  1827. SpDisplayScreen(SP_SCRN_REPAIR_HIVE_MENU,3,CLIENT_TOP+1);
  1828. //
  1829. // Calculate menu placement. Leave one blank line
  1830. // and one line for a frame.
  1831. //
  1832. MenuTopY = NextMessageTopLine + (SplangQueryMinimizeExtraSpacing() ? 2 : 5);
  1833. //
  1834. // Create a menu.
  1835. // First, find the longest string, so we can size the listbox accordingly
  1836. //
  1837. ListBoxWidth = HIVE_LIST_BOX_WIDTH; // It will be at least this wide
  1838. for (i = 0; i <= RepairHiveMax; i++ ) {
  1839. if (i == RepairHiveMax) {
  1840. SpFormatMessage(TemporaryBuffer,
  1841. sizeof(TemporaryBuffer),
  1842. SP_REPAIR_MENU_ITEM_CONTINUE);
  1843. } else {
  1844. #pragma prefast(suppress:201, "Logic takes care of the condition where buffer index refers beyond the buffer size")
  1845. SpFormatMessage(TemporaryBuffer,
  1846. sizeof(TemporaryBuffer),
  1847. MessageIds[i]);
  1848. }
  1849. if((curLBEntryWidth = SplangGetColumnCount(TemporaryBuffer)+(2*MENU_INDENT)) > ListBoxWidth) {
  1850. ListBoxWidth = min(curLBEntryWidth, MENU_WIDTH);
  1851. }
  1852. }
  1853. Menu = SpMnCreate(
  1854. MENU_LEFT_X,
  1855. MenuTopY,
  1856. ListBoxWidth,
  1857. HIVE_LIST_BOX_HEIGHT
  1858. );
  1859. ASSERT(Menu);
  1860. //
  1861. // Build up a menu of hives
  1862. //
  1863. for (i = 0; i <= RepairHiveMax; i++ ) {
  1864. if (i == RepairHiveSam) {
  1865. Selectable = FALSE;
  1866. } else {
  1867. Selectable = TRUE;
  1868. }
  1869. if (i == RepairHiveMax) {
  1870. SpFormatMessage(TemporaryBuffer,
  1871. sizeof(TemporaryBuffer),
  1872. SP_REPAIR_MENU_ITEM_CONTINUE);
  1873. } else {
  1874. #pragma prefast(suppress:201, "Logic takes care of the condition where buffer index refers beyond the buffer size")
  1875. SpFormatMessage(TemporaryBuffer,
  1876. sizeof(TemporaryBuffer),
  1877. MessageIds[i]);
  1878. p = TemporaryBuffer;
  1879. #pragma prefast(suppress:201, "Logic takes care of the condition where buffer index refers beyond the buffer size")
  1880. if (HiveLoaded[i] || ( i == RepairHiveSam )) {
  1881. p[1] = L' ';
  1882. } else {
  1883. p[1] = L'X';
  1884. }
  1885. }
  1886. SpMnAddItem(Menu,
  1887. TemporaryBuffer,
  1888. MENU_LEFT_X+MENU_INDENT,
  1889. ListBoxWidth-(2*MENU_INDENT),
  1890. Selectable,
  1891. i
  1892. );
  1893. }
  1894. InitialHighlight = RepairHiveMax;
  1895. //
  1896. // Initialize the status line.
  1897. //
  1898. SpDisplayStatusOptions(
  1899. DEFAULT_STATUS_ATTRIBUTE,
  1900. SP_STAT_ENTER_EQUALS_CHANGE,
  1901. SP_STAT_F3_EQUALS_EXIT,
  1902. 0
  1903. );
  1904. DisplayMenu:
  1905. //
  1906. // Display the menu
  1907. //
  1908. SpMnDisplay(
  1909. Menu,
  1910. InitialHighlight,
  1911. TRUE,
  1912. ValidKeys,
  1913. NULL,
  1914. NULL,
  1915. NULL,
  1916. &Keypress,
  1917. &OptionChosen
  1918. );
  1919. //
  1920. // Now act on the user's selection.
  1921. //
  1922. switch(Keypress) {
  1923. case KEY_F3:
  1924. SpConfirmExit();
  1925. break;
  1926. case ASCI_CR:
  1927. if (OptionChosen == RepairHiveMax) {
  1928. SpMnDestroy(Menu);
  1929. DetermineHivesToRepair = FALSE;
  1930. } else {
  1931. HiveLoaded[OptionChosen] ^= 1;
  1932. MenuItem = SpMnGetText(Menu, OptionChosen);
  1933. if ((HiveLoaded[OptionChosen] != 0) ||
  1934. (OptionChosen == RepairHiveSam)){
  1935. MenuItem[1] = L' ';
  1936. } else {
  1937. MenuItem[1] = L'X';
  1938. }
  1939. //
  1940. // Security and sam must go together.
  1941. //
  1942. HiveLoaded[RepairHiveSam] = HiveLoaded[RepairHiveSecurity];
  1943. InitialHighlight = OptionChosen;
  1944. goto DisplayMenu;
  1945. }
  1946. break;
  1947. }
  1948. }
  1949. UpdateTheHives:
  1950. //
  1951. // At this point user has decided which hives to repair.
  1952. // We will copy the hives from repair disk to
  1953. // Winnt\system32\config directory.
  1954. //
  1955. for (i = 0; i < RepairHiveMax; i++ ) {
  1956. // BCL - Seagate: Don't do ntuser.dat. As of 4/17/98, there is no
  1957. // copy of this file to copy from.
  1958. if ( SpDrEnabled() && i == RepairHiveUser ) {
  1959. continue;
  1960. }
  1961. if (HiveLoaded[i] == 0) {
  1962. //
  1963. // Form Target path
  1964. //
  1965. if( i != RepairHiveUser ) {
  1966. wcscpy(TemporaryBuffer, WinntPartition);
  1967. SpConcatenatePaths(TemporaryBuffer, WinntPartitionDirectory);
  1968. SpConcatenatePaths(TemporaryBuffer, L"\\SYSTEM32\\CONFIG");
  1969. TargetPath = SpDupStringW(TemporaryBuffer);
  1970. } else {
  1971. wcscpy(TemporaryBuffer, WinntPartition);
  1972. SpConcatenatePaths(TemporaryBuffer, WinntPartitionDirectory);
  1973. SpConcatenatePaths(TemporaryBuffer, DEFAULT_USER_PATH);
  1974. TargetPath = SpDupStringW(TemporaryBuffer);
  1975. }
  1976. Status = SppRepairFile(MasterSifHandle,
  1977. TargetPath,
  1978. HiveNames[i],
  1979. SourceDevicePath,
  1980. DirectoryOnSourceDevice,
  1981. HiveNames[i],
  1982. FALSE
  1983. );
  1984. if (!NT_SUCCESS(Status)) {
  1985. //
  1986. // Tell user we couldn't do it. Options are to continue or exit.
  1987. //
  1988. SpStartScreen(
  1989. SP_SCRN_REPAIR_HIVE_FAIL,
  1990. 3,
  1991. HEADER_HEIGHT+1,
  1992. FALSE,
  1993. FALSE,
  1994. DEFAULT_ATTRIBUTE
  1995. );
  1996. SpDisplayStatusOptions(
  1997. DEFAULT_STATUS_ATTRIBUTE,
  1998. SP_STAT_ENTER_EQUALS_CONTINUE,
  1999. SP_STAT_F3_EQUALS_EXIT,
  2000. 0
  2001. );
  2002. switch(SpWaitValidKey(ValidKeys1,NULL,NULL)) {
  2003. case ASCI_CR:
  2004. return;
  2005. break;
  2006. case KEY_F3:
  2007. SpConfirmExit();
  2008. break;
  2009. }
  2010. }
  2011. SpMemFree(TargetPath);
  2012. }
  2013. }
  2014. }
  2015. VOID
  2016. SpRepairWinnt(
  2017. IN PVOID LogFileHandle,
  2018. IN PVOID MasterSifHandle,
  2019. IN PWSTR SourceDevicePath,
  2020. IN PWSTR DirectoryOnSourceDevice
  2021. )
  2022. /*++
  2023. Routine Description:
  2024. This is a the top level repair rutine. It calls worker routines
  2025. for each repair options that user selected.
  2026. Arguments:
  2027. LogFileHandle - Handle of the setup.log
  2028. MasterSifHandle - Handle of the txtsetup.sif
  2029. SourceDevicePath - The NT name for the repair source device.
  2030. DirectoryOnSourceDevice - The directory name on the repair source
  2031. device which contains the source files.
  2032. Return Value:
  2033. None.
  2034. --*/
  2035. {
  2036. PWSTR SystemPartition, SystemPartitionDirectory;
  2037. PWSTR WinntPartition, WinntPartitionDirectory;
  2038. PWSTR HiveRepairSourceDevice, DirectoryOnHiveRepairSource;
  2039. //
  2040. // Initialize the diamond decompression engine.
  2041. //
  2042. SpdInitialize();
  2043. //
  2044. // Determine SystemPartition, SystemPartitionDirectory.
  2045. // WinntParition and WinntPartitionDirectory of the WINNT
  2046. // installation to be repaired.
  2047. //
  2048. SppGetRepairPathInformation(LogFileHandle,
  2049. &SystemPartition,
  2050. &SystemPartitionDirectory,
  2051. &WinntPartition,
  2052. &WinntPartitionDirectory
  2053. );
  2054. //
  2055. // If repair involves disk access, then run autochk on Nt and system
  2056. // partitions.
  2057. //
  2058. if( RepairItems[RepairFiles]
  2059. #if defined(_AMD64_) || defined(_X86_)
  2060. ||
  2061. RepairItems[RepairNvram]
  2062. #endif // defined(_AMD64_) || defined(_X86_)
  2063. ) {
  2064. PDISK_REGION SystemPartitionRegion;
  2065. PDISK_REGION WinntPartitionRegion;
  2066. WinntPartitionRegion = SpRegionFromNtName( WinntPartition,
  2067. PartitionOrdinalCurrent);
  2068. SystemPartitionRegion = SpRegionFromNtName( SystemPartition,
  2069. PartitionOrdinalCurrent);
  2070. if( !RepairNoCDROMDrive ) {
  2071. //
  2072. // If we know that the system doesn't have a CD-ROM drive,
  2073. // then don't even attempt to run autochk.
  2074. //
  2075. SpRunAutochkOnNtAndSystemPartitions( MasterSifHandle,
  2076. WinntPartitionRegion,
  2077. SystemPartitionRegion,
  2078. SourceDevicePath,
  2079. DirectoryOnSourceDevice,
  2080. NULL
  2081. );
  2082. }
  2083. }
  2084. //
  2085. // Verify and repair security of the directories that form the NT tree
  2086. // This needs to be done before repairing the hives because the
  2087. // system32\config directory might not be there anymore!
  2088. //
  2089. SppVerifyAndRepairNtTreeAccess(MasterSifHandle,
  2090. WinntPartition,
  2091. WinntPartitionDirectory,
  2092. SystemPartition,
  2093. SystemPartitionDirectory
  2094. );
  2095. #if 0
  2096. // BCL - Seagate - the RepairHives member has been removed from the
  2097. // struct
  2098. if (RepairItems[RepairHives]) {
  2099. //
  2100. // User has selected to repair hives. If user has provided the
  2101. // ER disk, we will copy the hive from ER disk to repair damaged
  2102. // hives. Otherwise we copy the hive from the directory where
  2103. // setup.log was loaded.
  2104. //
  2105. if (RepairFromErDisk) {
  2106. HiveRepairSourceDevice = L"\\device\\floppy0";
  2107. DirectoryOnHiveRepairSource = L"";
  2108. } else {
  2109. HiveRepairSourceDevice = WinntPartition;
  2110. wcscpy(TemporaryBuffer, WinntPartitionDirectory);
  2111. SpConcatenatePaths(TemporaryBuffer, SETUP_REPAIR_DIRECTORY);
  2112. DirectoryOnHiveRepairSource = SpDupStringW(TemporaryBuffer);
  2113. }
  2114. SppRepairHives(MasterSifHandle,
  2115. WinntPartition,
  2116. WinntPartitionDirectory,
  2117. HiveRepairSourceDevice,
  2118. DirectoryOnHiveRepairSource
  2119. );
  2120. if (!RepairFromErDisk) {
  2121. SpMemFree(DirectoryOnHiveRepairSource);
  2122. }
  2123. }
  2124. if (RepairItems[RepairFiles]) {
  2125. SppRepairWinntFiles(LogFileHandle,
  2126. MasterSifHandle,
  2127. SourceDevicePath,
  2128. DirectoryOnSourceDevice,
  2129. SystemPartition,
  2130. SystemPartitionDirectory,
  2131. WinntPartition,
  2132. WinntPartitionDirectory
  2133. );
  2134. }
  2135. #endif
  2136. //
  2137. // The code to repair nvram variables and boot sector is
  2138. // incorporated into SpStartSetup.
  2139. //
  2140. //
  2141. // Load the software hive, and and set the repair flag under Winlogon,
  2142. // so that winlogon can recreate the start menu groups and items for
  2143. // the default user.
  2144. //
  2145. SppRepairStartMenuGroupsAndItems( WinntPartition,
  2146. WinntPartitionDirectory );
  2147. //
  2148. // Terminate diamond.
  2149. //
  2150. SpdTerminate();
  2151. }
  2152. VOID
  2153. SppVerifyAndRepairNtTreeAccess(
  2154. IN PVOID MasterSifHandle,
  2155. IN PWSTR TargetDevicePath,
  2156. IN PWSTR DirectoryOnTargetDevice,
  2157. IN PWSTR SystemPartition,
  2158. IN PWSTR SystemPartitionDirectory
  2159. )
  2160. /*++
  2161. Routine Description:
  2162. This routine examines whether or not the directories that form the
  2163. NT tree are accessible, and set the appropriate security descriptor
  2164. in each directory, when necessary.
  2165. Arguments:
  2166. MasterSifHandle - Hanle of the txtsetup.sif
  2167. TargetDevicePath - supplies the nt name of the target device
  2168. DirectoryOnTargetDevice - the name of the winnt directory on target
  2169. device
  2170. SystemPartition - supplies the nt name of the target device (non-x86 platforms)
  2171. SystemPartitionDirectory - the name of the winnt directory on target
  2172. device (non-x86 platforms)
  2173. Return Value:
  2174. None.
  2175. --*/
  2176. {
  2177. ULONG Count, i;
  2178. PWSTR SectionName = L"WinntDirectories";
  2179. PWSTR DirectoryName;
  2180. PWSTR TargetPath;
  2181. PWSTR WinNtDirectory;
  2182. NTSTATUS Status;
  2183. SpDisplayStatusText(SP_STAT_SETUP_IS_EXAMINING_DIRS, DEFAULT_STATUS_ATTRIBUTE);
  2184. if(SpIsArc()){
  2185. //
  2186. // Make sure that on ARC platforms, the system partition directory
  2187. // exists (re-create it if it doesn't exist)
  2188. //
  2189. SpCreateDirectory(SystemPartition,NULL,SystemPartitionDirectory,0,0);
  2190. }
  2191. WinNtDirectory = ( PWSTR )SpMemAlloc( ( wcslen( TargetDevicePath ) + 1 +
  2192. wcslen( DirectoryOnTargetDevice ) + 1 +
  2193. 1 )*sizeof( WCHAR ) );
  2194. TargetPath = ( PWSTR )SpMemAlloc( 1024 );
  2195. if( ( WinNtDirectory == NULL ) ||
  2196. ( TargetPath == NULL ) ) {
  2197. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to allocate memory for WinNtDirectory \n"));
  2198. if( WinNtDirectory != NULL ) {
  2199. SpMemFree( WinNtDirectory );
  2200. }
  2201. if( TargetPath != NULL ) {
  2202. SpMemFree( TargetPath );
  2203. }
  2204. return;
  2205. }
  2206. wcscpy( WinNtDirectory, TargetDevicePath );
  2207. SpConcatenatePaths( WinNtDirectory, DirectoryOnTargetDevice );
  2208. Count = SpCountLinesInSection(MasterSifHandle, SectionName);
  2209. //
  2210. // Note that in the loop below, the maximum value for 'i' is 'Count'
  2211. // instead of 'Count-1'. This is because we need to create the directory
  2212. // 'Profiles\\Default User' which cannot be listed in txtsetup.sif.
  2213. // This is due to pre-install requirements, and DOS limitation regarding
  2214. // long file names.
  2215. //
  2216. for (i = 0; i <= Count; i++) {
  2217. if( i != Count ) {
  2218. DirectoryName = SpGetSectionLineIndex(MasterSifHandle,SectionName,i,0);
  2219. } else {
  2220. //
  2221. // Due to pre-installation requirements, and DOS limitation
  2222. // regarding long file names, the "Default User" directory
  2223. // is not specified on txtsetup.sif, as the other directories.
  2224. // This directory is treated as a special case in the
  2225. // repair process.
  2226. //
  2227. DirectoryName = DEFAULT_USER_PATH;
  2228. }
  2229. if(!DirectoryName) {
  2230. SppRepairReportError(FALSE,
  2231. SP_SCRN_REPAIR_INF_ERROR_0,
  2232. SP_TEXT_REPAIR_INF_ERROR_1,
  2233. SectionName,
  2234. i,
  2235. NULL);
  2236. continue;
  2237. }
  2238. wcscpy( TargetPath, WinNtDirectory );
  2239. //
  2240. // Make sure that TargetPath doesn't contain '\' as the last character
  2241. //
  2242. if(!((DirectoryName[0] == L'\\') && (DirectoryName[1] == 0))) {
  2243. SpConcatenatePaths( TargetPath, DirectoryName );
  2244. }
  2245. Status = SpVerifyFileAccess( TargetPath,
  2246. STANDARD_RIGHTS_READ |
  2247. FILE_READ_ATTRIBUTES |
  2248. FILE_LIST_DIRECTORY |
  2249. FILE_ADD_FILE |
  2250. FILE_ADD_SUBDIRECTORY |
  2251. FILE_TRAVERSE |
  2252. WRITE_DAC |
  2253. SYNCHRONIZE );
  2254. //
  2255. // If unable to access the directory, try to determine why.
  2256. // If it is because of access denied, change the directory security.
  2257. // If it is because the directory doesn't exist, then create it.
  2258. //
  2259. if( !NT_SUCCESS( Status ) ) {
  2260. if ((Status == STATUS_ACCESS_DENIED)||(Status == STATUS_PRIVILEGE_NOT_HELD) ) {
  2261. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Security of %ls, must be fixed. Status = %x\n", TargetPath, Status ));
  2262. Status = SpSetDefaultFileSecurity( TargetPath );
  2263. if( !NT_SUCCESS( Status ) ) {
  2264. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to change security of %ls. Status = %x\n", TargetPath, Status ));
  2265. }
  2266. } else if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  2267. if(((DirectoryName[0] == L'\\') && (DirectoryName[1] == 0))) {
  2268. //
  2269. // Create the target directory
  2270. //
  2271. SpCreateDirectory( TargetDevicePath,
  2272. NULL,
  2273. DirectoryOnTargetDevice,
  2274. 0,
  2275. 0);
  2276. } else {
  2277. SpCreateDirectory( TargetDevicePath,
  2278. DirectoryOnTargetDevice,
  2279. DirectoryName,
  2280. 0,
  2281. 0);
  2282. }
  2283. } else {
  2284. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to access directory %ls. Status = %x\n", TargetPath, Status ));
  2285. }
  2286. }
  2287. }
  2288. if( WinNtDirectory != NULL ) {
  2289. SpMemFree( WinNtDirectory );
  2290. }
  2291. if( TargetPath != NULL ) {
  2292. SpMemFree( TargetPath );
  2293. }
  2294. return;
  2295. }
  2296. VOID
  2297. SppVerifyAndRepairVdmFiles(
  2298. IN PVOID LogFileHandle,
  2299. IN PWSTR TargetDevicePath,
  2300. IN PWSTR DirectoryOnTargetDevice,
  2301. IN PBOOLEAN RepairWithoutConfirming
  2302. )
  2303. /*++
  2304. Routine Description:
  2305. This routine repairs the Vdm configuration files listed on
  2306. 'Files.InRepairDirectory' of setup.log. Currently, such files are:
  2307. autoexec.nt and config.nt. It is assumed that files in this section
  2308. will be copied from the emergency repair disk, or from the repair
  2309. directory.
  2310. Arguments:
  2311. LogFileHandle - Handle of the setup.log
  2312. TargetDevicePath - supplies the nt name of the target device
  2313. DirectoryOnTargetDevice - the name of the winnt directory on target
  2314. device
  2315. RepairWithoutConfirming - Pointer to a flag that indicates whether or not
  2316. setup should repair files without confirming
  2317. with the user.
  2318. Return Value:
  2319. None.
  2320. --*/
  2321. {
  2322. PWSTR FullTargetName, ChecksumString;
  2323. PWSTR TargetDirectory, TargetFileName;
  2324. PWSTR SourceFileName;
  2325. ULONG Checksum, FileChecksum, PrefixLength, Length, Count, i;
  2326. BOOLEAN IsNtImage, IsValid, RepairFile;
  2327. BOOLEAN RedrawGauge = TRUE;
  2328. FILE_TO_COPY FileToCopy;
  2329. PWSTR DevicePath, Directory;
  2330. PWSTR SectionName = SIF_NEW_REPAIR_FILES_IN_REPAIR_DIR;
  2331. //
  2332. // Allocate a SMALL buffer for local use and init FileToCopy struct
  2333. //
  2334. TargetDirectory = NULL;
  2335. FullTargetName = SpMemAlloc(1024);
  2336. *FullTargetName = 0;
  2337. FileToCopy.Next = NULL;
  2338. FileToCopy.Flags = COPY_ALWAYS;
  2339. FileToCopy.AbsoluteTargetDirectory = TRUE;
  2340. FileToCopy.TargetDevicePath = TargetDevicePath;
  2341. SpConcatenatePaths(FullTargetName,TargetDevicePath);
  2342. PrefixLength = wcslen(FullTargetName);
  2343. Count = SpCountLinesInSection(LogFileHandle,SectionName);
  2344. for (i = 0; i < Count; i++) {
  2345. if (RedrawGauge) {
  2346. SppRepairScreenRepaint(NULL, NULL, TRUE);
  2347. RedrawGauge = FALSE;
  2348. }
  2349. SpTickGauge(RepairGauge);
  2350. //
  2351. // Initialize target fullname to be DevicePath+Directory for
  2352. // system partition file or DevicePath for Winnt files
  2353. //
  2354. FullTargetName[PrefixLength] = (WCHAR)NULL;
  2355. //
  2356. // If we allocate space for TargetDirectory we must free it.
  2357. //
  2358. if (TargetDirectory) {
  2359. SpMemFree(TargetDirectory);
  2360. TargetDirectory = NULL;
  2361. }
  2362. TargetFileName = SpGetKeyName(LogFileHandle,SectionName,i);
  2363. if(!TargetFileName) {
  2364. SppRepairReportError(FALSE,
  2365. SP_SCRN_REPAIR_INF_ERROR_0,
  2366. SP_TEXT_REPAIR_INF_ERROR_1,
  2367. SectionName,
  2368. i,
  2369. NULL);
  2370. RedrawGauge = TRUE;
  2371. continue;
  2372. }
  2373. SpConcatenatePaths(FullTargetName,TargetFileName);
  2374. SpDisplayStatusText(SP_STAT_EXAMINING_WINNT,
  2375. DEFAULT_STATUS_ATTRIBUTE,
  2376. TargetFileName);
  2377. ChecksumString = SpGetSectionLineIndex(LogFileHandle,SectionName,i,1);
  2378. if(!ChecksumString) {
  2379. SppRepairReportError(FALSE,
  2380. SP_SCRN_REPAIR_INF_ERROR_0,
  2381. SP_TEXT_REPAIR_INF_ERROR_1,
  2382. SectionName,
  2383. i,
  2384. NULL);
  2385. RedrawGauge = TRUE;
  2386. continue;
  2387. }
  2388. Checksum = (ULONG)SpStringToLong(ChecksumString, NULL, 16);
  2389. SpValidateAndChecksumFile(NULL,FullTargetName,&IsNtImage,&FileChecksum,&IsValid);
  2390. //
  2391. // If the image is invalid or the file on the target is not the
  2392. // original file copied by setup, we will recopy it.
  2393. //
  2394. if (!IsValid || FileChecksum != Checksum) {
  2395. //
  2396. // Ask user if he wants to repair the file
  2397. //
  2398. RepairFile = ( *RepairWithoutConfirming )?
  2399. TRUE :
  2400. SppRepairReportError(
  2401. TRUE,
  2402. SP_SCRN_REPAIR_FILE_MISMATCH,
  2403. SP_TEXT_REPAIR_INF_ERROR_4,
  2404. TargetFileName,
  2405. i,
  2406. RepairWithoutConfirming);
  2407. RedrawGauge = TRUE;
  2408. if (!RepairFile) {
  2409. continue;
  2410. }
  2411. SpDisplayStatusText(SP_STAT_REPAIR_WINNT,
  2412. DEFAULT_STATUS_ATTRIBUTE,
  2413. TargetFileName);
  2414. //
  2415. // TargetName contains path and filename.
  2416. // We need to seperate them.
  2417. //
  2418. TargetDirectory = SpDupStringW(TargetFileName);
  2419. Length = wcslen(TargetDirectory);
  2420. while (Length) {
  2421. if (TargetDirectory[Length] == L'\\') {
  2422. TargetDirectory[Length] = 0;
  2423. TargetFileName = &TargetDirectory[Length + 1];
  2424. break;
  2425. } else {
  2426. Length--;
  2427. }
  2428. }
  2429. if (Length == 0) {
  2430. SppRepairReportError(FALSE,
  2431. SP_SCRN_REPAIR_INF_ERROR_0,
  2432. SP_TEXT_REPAIR_INF_ERROR_1,
  2433. SectionName,
  2434. i,
  2435. NULL);
  2436. RedrawGauge = TRUE;
  2437. continue;
  2438. }
  2439. FileToCopy.TargetFilename = TargetFileName;
  2440. FileToCopy.TargetDirectory = TargetDirectory;
  2441. SourceFileName = SpGetSectionLineIndex(LogFileHandle,SectionName,i,0);
  2442. if (!SourceFileName) {
  2443. SppRepairReportError(FALSE,
  2444. SP_SCRN_REPAIR_INF_ERROR_0,
  2445. SP_TEXT_REPAIR_INF_ERROR_1,
  2446. SectionName,
  2447. i,
  2448. NULL);
  2449. RedrawGauge = TRUE;
  2450. continue;
  2451. }
  2452. FileToCopy.SourceFilename = SourceFileName;
  2453. //
  2454. // Find out whether the source file should come from the
  2455. // Emergency Repair Disk or the Repair directory
  2456. //
  2457. if (RepairFromErDisk) {
  2458. BOOLEAN rs;
  2459. PWSTR szDiskName;
  2460. PWSTR szDevicePath = SpDupStringW(L"\\device\\floppy0");
  2461. //
  2462. // Fetch the generic repair disk name.
  2463. //
  2464. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),
  2465. SP_TEXT_REPAIR_DISK_NAME);
  2466. szDiskName = SpDupStringW(TemporaryBuffer);
  2467. //
  2468. // Prompt for the disk, based on the setup media type.
  2469. //
  2470. rs = SpPromptForDisk(
  2471. szDiskName,
  2472. szDevicePath,
  2473. SETUP_LOG_FILENAME,
  2474. FALSE, // if disk is in already dont prompt
  2475. FALSE, // allow escape
  2476. TRUE, // warn for multiple prompts
  2477. NULL // don't care about redraw flag
  2478. );
  2479. SpMemFree(szDiskName);
  2480. SpMemFree(szDevicePath);
  2481. RedrawGauge = TRUE;
  2482. if (rs == FALSE) {
  2483. continue;
  2484. }
  2485. DevicePath = L"\\device\\floppy0";
  2486. wcscpy( TemporaryBuffer, L"\\" );
  2487. Directory = SpDupStringW(TemporaryBuffer); // OemSourceDirectory;
  2488. } else {
  2489. RedrawGauge = TRUE;
  2490. DevicePath = TargetDevicePath;
  2491. wcscpy( TemporaryBuffer, DirectoryOnTargetDevice );
  2492. SpConcatenatePaths( TemporaryBuffer, SETUP_REPAIR_DIRECTORY );
  2493. Directory = SpDupStringW(TemporaryBuffer);
  2494. }
  2495. //
  2496. // Copy the file.
  2497. //
  2498. SpCopyFileWithRetry(
  2499. &FileToCopy,
  2500. DevicePath,
  2501. Directory,
  2502. NULL,
  2503. NULL, // TargetRoot -> NULL
  2504. 0, // SystemPartitionFiles ? ATTR_RHS : 0,
  2505. SppRepairScreenRepaint,
  2506. NULL, // Do not want checksum
  2507. NULL, // Do not want to know if file was skipped
  2508. 0
  2509. );
  2510. SpMemFree( Directory );
  2511. }
  2512. }
  2513. SpMemFree(FullTargetName);
  2514. if (RedrawGauge) {
  2515. SppRepairScreenRepaint(NULL, NULL, TRUE);
  2516. }
  2517. }