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

1018 lines
26 KiB

  1. #include "spprecmp.h"
  2. #pragma hdrstop
  3. /*++
  4. Revision History
  5. Michael Peterson (Seagate Software)
  6. + Modified SpIsNtInDirectory() so that it always returns FALSE if DR is
  7. in effect.
  8. --*/
  9. PWSTR *NtDirectoryList;
  10. ULONG NtDirectoryCount;
  11. BOOLEAN
  12. SpNFilesExist(
  13. IN OUT PWSTR PathName,
  14. IN PWSTR *Files,
  15. IN ULONG FileCount,
  16. IN BOOLEAN Directories
  17. )
  18. {
  19. UNICODE_STRING UnicodeString;
  20. OBJECT_ATTRIBUTES Obja;
  21. HANDLE Handle;
  22. ULONG i;
  23. PWSTR FilenamePart;
  24. IO_STATUS_BLOCK IoStatusBlock;
  25. NTSTATUS Status;
  26. //
  27. // No reason to call this routine to check for 0 files.
  28. //
  29. ASSERT(FileCount);
  30. //
  31. // Stick a backslash on the end of the path part if necessary.
  32. //
  33. SpConcatenatePaths(PathName,L"");
  34. FilenamePart = PathName + wcslen(PathName);
  35. //
  36. // Check each file. If any one of then doesn't exist,
  37. // then return FALSE.
  38. //
  39. for(i=0; i<FileCount; i++) {
  40. //
  41. // Restore PathName and concatenate the new filename
  42. //
  43. *FilenamePart = L'\0';
  44. SpConcatenatePaths(PathName, Files[i]);
  45. INIT_OBJA(&Obja,&UnicodeString,PathName);
  46. Status = ZwCreateFile(
  47. &Handle,
  48. FILE_READ_ATTRIBUTES,
  49. &Obja,
  50. &IoStatusBlock,
  51. NULL,
  52. 0,
  53. FILE_SHARE_READ | FILE_SHARE_WRITE,
  54. FILE_OPEN,
  55. FILE_OPEN_REPARSE_POINT | (Directories ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE),
  56. NULL,
  57. 0
  58. );
  59. if(NT_SUCCESS(Status)) {
  60. ZwClose(Handle);
  61. } else {
  62. *FilenamePart = 0;
  63. return(FALSE);
  64. }
  65. }
  66. //
  67. // All exist. Return TRUE.
  68. //
  69. *FilenamePart = 0;
  70. return(TRUE);
  71. }
  72. BOOLEAN
  73. SpIsNtInDirectory(
  74. IN PDISK_REGION Region,
  75. IN PWSTR Directory
  76. )
  77. /*++
  78. Routine Description:
  79. Determine whether Windows NT is present on a partition in one of a
  80. set of given directories. This determination is based on the presence
  81. of certain windows nt system files and directories.
  82. Arguments:
  83. Region - supplies the region descriptor for the partition to check.
  84. Directory - supplies the path to check for a windows nt installation.
  85. Return Value:
  86. TRUE if we think we've found Windows NT in the given directory on
  87. the given partition.
  88. --*/
  89. {
  90. PWSTR NTDirectories[3] = { L"system32", L"system32\\drivers", L"system32\\config" };
  91. PWSTR NTFiles[2] = { L"system32\\ntoskrnl.exe", L"system32\\ntdll.dll" };
  92. PWSTR PaeNTFiles[2] = { L"system32\\ntkrnlpa.exe", L"system32\\ntdll.dll" };
  93. PWSTR OpenPath;
  94. BOOLEAN rc;
  95. if( SpDrEnabled() && ! RepairWinnt )
  96. {
  97. return( FALSE );
  98. }
  99. OpenPath = SpMemAlloc(1024);
  100. //
  101. // Place the fixed part of the name into the buffer.
  102. //
  103. SpNtNameFromRegion(
  104. Region,
  105. OpenPath,
  106. 1024,
  107. PartitionOrdinalCurrent
  108. );
  109. SpConcatenatePaths(OpenPath,Directory);
  110. if(SpNFilesExist(OpenPath, NTDirectories, ELEMENT_COUNT(NTDirectories), TRUE) &&
  111. (SpNFilesExist(OpenPath, NTFiles, ELEMENT_COUNT(NTFiles), FALSE) ||
  112. SpNFilesExist(OpenPath, PaeNTFiles, ELEMENT_COUNT(PaeNTFiles), FALSE))) {
  113. rc = TRUE;
  114. } else {
  115. rc = FALSE;
  116. }
  117. SpMemFree(OpenPath);
  118. return(rc);
  119. }
  120. ULONG
  121. SpRemoveInstallation(
  122. IN PDISK_REGION Region,
  123. IN PWSTR PartitionPath,
  124. IN PWSTR Directory
  125. )
  126. {
  127. HANDLE Handle;
  128. NTSTATUS Status;
  129. PWSTR FileName;
  130. ULONG Space = 0;
  131. ULONG ClusterSize;
  132. ULONG bps;
  133. PVOID Gauge;
  134. PWSTR Filename;
  135. ULONG FileCount;
  136. ULONG FileSize;
  137. ULONG i;
  138. OBJECT_ATTRIBUTES Obja;
  139. UNICODE_STRING UnicodeString;
  140. IO_STATUS_BLOCK IoStatusBlock;
  141. ULONG ErrLine;
  142. PVOID Inf;
  143. BOOLEAN OldFormatSetupLogFile;
  144. PWSTR SectionName;
  145. HANDLE TempHandle;
  146. ULONG RootDirLength;
  147. PUCHAR UBuffer;
  148. PUCHAR Buffer;
  149. FileName = SpMemAlloc(1024);
  150. //
  151. // Fetch the number of bytes in a sector.
  152. //
  153. bps = HardDisks[Region->DiskNumber].Geometry.BytesPerSector;
  154. //
  155. // Get cluster size from the BPB.
  156. //
  157. ASSERT(Region->Filesystem >= FilesystemFirstKnown);
  158. Status = SpOpenPartition(
  159. HardDisks[Region->DiskNumber].DevicePath,
  160. SpPtGetOrdinal(Region,PartitionOrdinalCurrent),
  161. &Handle,
  162. FALSE
  163. );
  164. if(!NT_SUCCESS(Status)) {
  165. goto xx0;
  166. }
  167. UBuffer = SpMemAlloc(2*bps);
  168. Buffer = ALIGN(UBuffer,bps);
  169. Status = SpReadWriteDiskSectors(
  170. Handle,
  171. 0,
  172. 1,
  173. bps,
  174. Buffer,
  175. FALSE
  176. );
  177. if(!NT_SUCCESS(Status)) {
  178. ZwClose(Handle);
  179. SpMemFree(UBuffer);
  180. goto xx0;
  181. }
  182. //
  183. // Make sure this sector appears to hold a valid boot sector
  184. // for a hard disk.
  185. //
  186. // "55AA" was not presented by DOS 5.0 for NEC98,
  187. // so must not to check "55aa" in BPB,
  188. //
  189. if(((!IsNEC_98) &&
  190. ((Buffer[510] == 0x55) && (Buffer[511] == 0xaa) && (Buffer[21] == 0xf8))) ||
  191. ((IsNEC_98) && (Buffer[21] == 0xf8))) { //NEC98
  192. //
  193. // bps * spc.
  194. //
  195. ClusterSize = (ULONG)U_USHORT(Buffer+11) * (ULONG)Buffer[13];
  196. } else {
  197. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpRemoveInstallation: sector 0 on %ws is invalid\n",PartitionPath));
  198. Status = STATUS_UNSUCCESSFUL;
  199. }
  200. ZwClose(Handle);
  201. SpMemFree(UBuffer);
  202. if(!NT_SUCCESS(Status)) {
  203. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpRemoveInstallation: can't get cluster size on %ws\n",PartitionPath));
  204. goto xx0;
  205. }
  206. //
  207. // Find out if the repair directory exists, if it does exist load
  208. // setup.log from the repair directory. Otherwise, load setup.log
  209. // from the WinNt directory
  210. //
  211. wcscpy(FileName,PartitionPath);
  212. SpConcatenatePaths(FileName,Directory);
  213. RootDirLength = wcslen(FileName);
  214. SpConcatenatePaths(FileName,SETUP_REPAIR_DIRECTORY);
  215. INIT_OBJA( &Obja, &UnicodeString, FileName );
  216. Status = ZwOpenFile( &TempHandle,
  217. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  218. &Obja,
  219. &IoStatusBlock,
  220. FILE_SHARE_READ,
  221. FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
  222. );
  223. if( !NT_SUCCESS( Status ) ) {
  224. FileName[ RootDirLength ] = L'\0';
  225. } else {
  226. ZwClose( TempHandle );
  227. }
  228. SpConcatenatePaths(FileName,SETUP_LOG_FILENAME);
  229. //
  230. // Load setup.log from the given path.
  231. //
  232. Status = SpLoadSetupTextFile(FileName,NULL,0,&Inf,&ErrLine,TRUE,FALSE);
  233. if(!NT_SUCCESS(Status)) {
  234. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpRemoveInstallation: can't load inf file %ws (%lx)\n",FileName,Status));
  235. while(1) {
  236. ULONG ks[2] = { ASCI_CR, 0 };
  237. SpStartScreen(
  238. SP_SCRN_CANT_LOAD_SETUP_LOG,
  239. 3,
  240. HEADER_HEIGHT+2,
  241. FALSE,
  242. FALSE,
  243. DEFAULT_ATTRIBUTE,
  244. FileName + wcslen(PartitionPath) // skip \device\harddiskx\partitiony
  245. );
  246. SpDisplayStatusOptions(
  247. DEFAULT_STATUS_ATTRIBUTE,
  248. SP_STAT_ENTER_EQUALS_CONTINUE,
  249. 0
  250. );
  251. switch(SpWaitValidKey(ks,NULL,NULL)) {
  252. case ASCI_CR:
  253. goto xx0;
  254. }
  255. }
  256. }
  257. //
  258. // Go through all files in the [Repair.WinntFiles] section
  259. //
  260. SpStartScreen(
  261. SP_SCRN_WAIT_REMOVING_NT_FILES,
  262. 0,
  263. 8,
  264. TRUE,
  265. FALSE,
  266. DEFAULT_ATTRIBUTE
  267. );
  268. //
  269. // Determine whether setup.log has the new or old style
  270. //
  271. if( OldFormatSetupLogFile = !IsSetupLogFormatNew( Inf ) ) {
  272. SectionName = SIF_REPAIRWINNTFILES;
  273. } else {
  274. SectionName = SIF_NEW_REPAIR_WINNTFILES;
  275. }
  276. FileCount = SpCountLinesInSection(Inf,SectionName);
  277. SpFormatMessage(
  278. TemporaryBuffer,
  279. sizeof(TemporaryBuffer),
  280. SP_TEXT_SETUP_IS_REMOVING_FILES
  281. );
  282. Gauge = SpCreateAndDisplayGauge(
  283. FileCount,
  284. 0,
  285. VideoVars.ScreenHeight - STATUS_HEIGHT - (3*GAUGE_HEIGHT/2),
  286. TemporaryBuffer,
  287. NULL,
  288. GF_PERCENTAGE,
  289. 0
  290. );
  291. //
  292. // Clear the status area.
  293. //
  294. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,0);
  295. //
  296. // Set the status text in the lower right portion of the screen
  297. // to "Removing:" in preparation for displaying filenames as
  298. // files are deleted. The 12 is for an 8.3 name.
  299. //
  300. SpDisplayStatusActionLabel(SP_STAT_REMOVING,12);
  301. for(i=0; i<FileCount; i++) {
  302. if( OldFormatSetupLogFile ) {
  303. Filename = SpGetSectionLineIndex(Inf,SectionName,i,1);
  304. } else {
  305. Filename = SpGetKeyName(Inf,SectionName,i);
  306. }
  307. if(Filename) {
  308. PWCHAR p = wcsrchr(Filename,L'\\');
  309. if(p) {
  310. p++;
  311. } else {
  312. p = Filename;
  313. }
  314. #ifdef _X86_
  315. {
  316. //
  317. // Don't remove files in the system directory.
  318. // We might have installed into the windows directory
  319. // so removing files in the system directory would
  320. // wipe out the user's fonts (which are shared between
  321. // 3.1 and nt).
  322. //
  323. PWSTR dup = SpDupStringW(Filename);
  324. SpStringToLower(dup);
  325. if(wcsstr(dup,L"\\system\\")) {
  326. SpMemFree(dup);
  327. SpTickGauge(Gauge);
  328. continue;
  329. }
  330. SpMemFree(dup);
  331. }
  332. #endif
  333. SpDisplayStatusActionObject(p);
  334. //
  335. // Form the full pathname of the file being deleted.
  336. //
  337. wcscpy(FileName,PartitionPath);
  338. SpConcatenatePaths(FileName,Filename);
  339. //
  340. // Open the file.
  341. //
  342. INIT_OBJA(&Obja,&UnicodeString,FileName);
  343. Status = ZwCreateFile(
  344. &Handle,
  345. FILE_READ_ATTRIBUTES,
  346. &Obja,
  347. &IoStatusBlock,
  348. NULL,
  349. 0,
  350. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  351. FILE_OPEN, // open if exists
  352. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
  353. NULL,
  354. 0
  355. );
  356. if(!NT_SUCCESS(Status)) {
  357. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpRemoveInstallation: unable to open %ws (%lx)\n",FileName,Status));
  358. } else {
  359. //
  360. // Get the file size.
  361. //
  362. Status = SpGetFileSize(Handle,&FileSize);
  363. if(!NT_SUCCESS(Status)) {
  364. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpRemoveInstallation: unable to get %ws file size (%lx)\n",FileName,Status));
  365. FileSize = 0;
  366. } else {
  367. //
  368. // Add the size of this file to the running total.
  369. //
  370. if(FileSize % ClusterSize) {
  371. FileSize += ClusterSize - (FileSize % ClusterSize);
  372. }
  373. Space += FileSize;
  374. }
  375. ZwClose(Handle);
  376. //
  377. // Delete the file
  378. //
  379. Status = SpDeleteFile(FileName,NULL,NULL);
  380. if(!NT_SUCCESS(Status)) {
  381. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to delete %ws (%lx)\n",FileName,Status));
  382. Space -= FileSize;
  383. }
  384. }
  385. }
  386. SpTickGauge(Gauge);
  387. }
  388. SpFreeTextFile(Inf);
  389. SpDestroyGauge(Gauge);
  390. SpDisplayStatusActionLabel(0,0);
  391. xx0:
  392. SpMemFree(FileName);
  393. return(Space);
  394. }
  395. BOOLEAN
  396. SpIsNtOnPartition(
  397. IN PDISK_REGION Region
  398. )
  399. /*++
  400. Routine Description:
  401. Determine whether there is any Windows NT installed on
  402. a given partition.
  403. Arguments:
  404. PartitionPath - supplies NT path to partition on which we
  405. should look for NT installations.
  406. Return Value:
  407. TRUE if any NT installations were found.
  408. FALSE if not.
  409. --*/
  410. {
  411. ULONG i;
  412. SpGetNtDirectoryList(&NtDirectoryList,&NtDirectoryCount);
  413. for(i=0; i<NtDirectoryCount; i++) {
  414. if(SpIsNtInDirectory(Region,NtDirectoryList[i])) {
  415. return(TRUE);
  416. }
  417. }
  418. return(FALSE);
  419. }
  420. BOOLEAN
  421. SpAllowRemoveNt(
  422. IN PDISK_REGION Region,
  423. IN PWSTR DriveSpec, OPTIONAL
  424. IN BOOLEAN RescanForNTs,
  425. IN ULONG ScreenMsgId,
  426. OUT PULONG SpaceFreed
  427. )
  428. /*++
  429. Routine Description:
  430. Arguments:
  431. ScreenMsgId - supplies the message id of the text that will be
  432. printed above the menu of located nt directories,
  433. to supply instructions, etc.
  434. SpaceFreed - receives amount of disk space created by removing a
  435. Windows NT tree, if this function returns TRUE.
  436. Return Value:
  437. TRUE if any files were actually removed.
  438. FALSE otherwise.
  439. If an error occured, the user will have already been told about it.
  440. --*/
  441. {
  442. ULONG i;
  443. ULONG NtCount;
  444. PULONG MenuOrdinals;
  445. PWSTR *MenuItems;
  446. PWSTR *MenuTemp;
  447. BOOLEAN rc,b;
  448. BOOLEAN Add;
  449. ULONG MenuWidth,MenuLeftX;
  450. PVOID Menu;
  451. PWSTR PartitionPath;
  452. CLEAR_CLIENT_SCREEN();
  453. SpDisplayStatusText(SP_STAT_EXAMINING_DISK_CONFIG,DEFAULT_STATUS_ATTRIBUTE);
  454. PartitionPath = SpMemAlloc(512);
  455. //
  456. // Form the nt pathname for this partition.
  457. //
  458. SpNtNameFromRegion(
  459. Region,
  460. PartitionPath,
  461. 512,
  462. PartitionOrdinalCurrent
  463. );
  464. //
  465. // Assume nothing deleted.
  466. //
  467. rc = FALSE;
  468. //
  469. // Go look for Windows NT installations.
  470. //
  471. if(RescanForNTs) {
  472. SpGetNtDirectoryList(&NtDirectoryList,&NtDirectoryCount);
  473. }
  474. if(!NtDirectoryCount) {
  475. goto xx0;
  476. }
  477. //
  478. // Determine whether any of the NT trees we found are
  479. // on the given partition, and build an association between
  480. // NT trees and their ordinal positions in the menu we will
  481. // present to the user, and the menu itself.
  482. //
  483. NtCount = 0;
  484. MenuOrdinals = SpMemAlloc((NtDirectoryCount+1)*sizeof(ULONG));
  485. MenuItems = SpMemAlloc((NtDirectoryCount+1)*sizeof(PWSTR));
  486. //
  487. // Eliminate potential duplicate entries in the menu
  488. // to be presented to the user.
  489. //
  490. MenuTemp = SpMemAlloc(NtDirectoryCount*sizeof(PWSTR));
  491. for(i=0; i<NtDirectoryCount; i++) {
  492. WCHAR FullName[128];
  493. ULONG j;
  494. _snwprintf(
  495. FullName,
  496. (sizeof(FullName)/sizeof(WCHAR))-1,
  497. L"%s%s",
  498. DriveSpec ? DriveSpec : L"",
  499. NtDirectoryList[i]
  500. );
  501. FullName[(sizeof(FullName)/sizeof(WCHAR))-1] = 0;
  502. //
  503. // If the name is not already in the list, then add it.
  504. //
  505. for(Add=TRUE,j=0; Add && (j<i); j++) {
  506. if(MenuTemp[j] && !_wcsicmp(FullName,MenuTemp[j])) {
  507. Add = FALSE;
  508. }
  509. }
  510. MenuTemp[i] = Add ? SpDupStringW(FullName) : NULL;
  511. }
  512. //
  513. // Construct the menu to be presented to the user by looking in the
  514. // list of directories constructed above.
  515. //
  516. for(i=0; i<NtDirectoryCount; i++) {
  517. if(MenuTemp[i] && SpIsNtInDirectory(Region,NtDirectoryList[i])) {
  518. MenuOrdinals[NtCount] = i;
  519. MenuItems[NtCount] = SpDupStringW(MenuTemp[i]);
  520. NtCount++;
  521. }
  522. }
  523. for(i=0; i<NtDirectoryCount; i++) {
  524. if(MenuTemp[i]) {
  525. SpMemFree(MenuTemp[i]);
  526. }
  527. }
  528. SpMemFree(MenuTemp);
  529. //
  530. // If we found any nt directories on this partition,
  531. // make a menu to present to the user. Otherwise we
  532. // are done here.
  533. //
  534. if(!NtCount) {
  535. goto xx1;
  536. }
  537. MenuOrdinals = SpMemRealloc(MenuOrdinals,(NtCount+1) * sizeof(ULONG));
  538. MenuItems = SpMemRealloc(MenuItems,(NtCount+1) * sizeof(PWSTR));
  539. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_TEXT_REMOVE_NO_FILES);
  540. MenuItems[NtCount] = SpDupStringW(TemporaryBuffer);
  541. //
  542. // Determine the width of the widest item.
  543. //
  544. MenuWidth = 0;
  545. for(i=0; i<=NtCount; i++) {
  546. if(SplangGetColumnCount(MenuItems[i]) > MenuWidth) {
  547. MenuWidth = SplangGetColumnCount(MenuItems[i]);
  548. }
  549. }
  550. //
  551. // Use 80-column screen here because that's how the screen text
  552. // above the menu will be formatted.
  553. //
  554. MenuLeftX = 40 - (MenuWidth/2);
  555. //
  556. // Create menu and populate it.
  557. //
  558. SpDisplayScreen(ScreenMsgId,3,HEADER_HEIGHT+1);
  559. Menu = SpMnCreate(
  560. MenuLeftX,
  561. NextMessageTopLine+(SplangQueryMinimizeExtraSpacing() ? 1 : 2),
  562. MenuWidth,
  563. VideoVars.ScreenHeight-STATUS_HEIGHT-NextMessageTopLine-(SplangQueryMinimizeExtraSpacing() ? 2 : 3)
  564. );
  565. for(i=0; i<=NtCount; i++) {
  566. SpMnAddItem(Menu,MenuItems[i],MenuLeftX,MenuWidth,TRUE,i);
  567. }
  568. //
  569. // Present the menu of installations available for removal
  570. // on this partition and await a choice.
  571. //
  572. b = TRUE;
  573. do {
  574. ULONG Keys[4] = { ASCI_CR,KEY_F3,ASCI_ESC,0 };
  575. ULONG Mnemonics[2] = { MnemonicRemoveFiles,0 };
  576. ULONG key;
  577. ULONG_PTR Choice;
  578. SpDisplayScreen(ScreenMsgId,3,HEADER_HEIGHT+1);
  579. SpDisplayStatusOptions(
  580. DEFAULT_STATUS_ATTRIBUTE,
  581. SP_STAT_ESC_EQUALS_CANCEL,
  582. SP_STAT_ENTER_EQUALS_SELECT,
  583. SP_STAT_F3_EQUALS_EXIT,
  584. 0
  585. );
  586. nextkey:
  587. SpMnDisplay(Menu,NtCount,FALSE,Keys,NULL,NULL,&key,&Choice);
  588. if(key == KEY_F3) {
  589. SpConfirmExit();
  590. } else if(key == ASCI_ESC) {
  591. break;
  592. } else if(key == ASCI_CR) {
  593. if(Choice == NtCount) {
  594. b = FALSE;
  595. } else {
  596. BOOLEAN keys;
  597. ULONG ValidKeys2[3] = { KEY_F3,ASCI_ESC,0 };
  598. //
  599. // User wants to actually remove an installation.
  600. // Confirm and then do that here.
  601. //
  602. redraw2:
  603. SpStartScreen(
  604. SP_SCRN_REMOVE_EXISTING_NT,
  605. 3,
  606. HEADER_HEIGHT+1,
  607. FALSE,
  608. FALSE,
  609. DEFAULT_ATTRIBUTE,
  610. MenuItems[Choice]
  611. );
  612. SpDisplayStatusOptions(
  613. DEFAULT_STATUS_ATTRIBUTE,
  614. SP_STAT_R_EQUALS_REMOVE_FILES,
  615. SP_STAT_ESC_EQUALS_CANCEL,
  616. SP_STAT_F3_EQUALS_EXIT,
  617. 0
  618. );
  619. keys = TRUE;
  620. while(keys) {
  621. switch(SpWaitValidKey(ValidKeys2,NULL,Mnemonics)) {
  622. case KEY_F3:
  623. SpConfirmExit();
  624. goto redraw2;
  625. case ASCI_ESC:
  626. keys = FALSE;
  627. break;
  628. default:
  629. //
  630. // Must be r=remove files.
  631. //
  632. *SpaceFreed = SpRemoveInstallation(
  633. Region,
  634. PartitionPath,
  635. NtDirectoryList[MenuOrdinals[Choice]]
  636. );
  637. rc = TRUE;
  638. SpStartScreen(
  639. SP_SCRN_DONE_REMOVING_EXISTING_NT,
  640. 4,
  641. HEADER_HEIGHT+3,
  642. FALSE,
  643. FALSE,
  644. DEFAULT_ATTRIBUTE,
  645. *SpaceFreed
  646. );
  647. SpDisplayStatusOptions(
  648. DEFAULT_STATUS_ATTRIBUTE,
  649. SP_STAT_ENTER_EQUALS_CONTINUE,
  650. 0
  651. );
  652. while(SpInputGetKeypress() != ASCI_CR) ;
  653. keys = FALSE;
  654. b = FALSE;
  655. break;
  656. }
  657. }
  658. }
  659. } else {
  660. goto nextkey;
  661. }
  662. } while(b);
  663. SpMnDestroy(Menu);
  664. xx1:
  665. for(i=0; i<=NtCount; i++) {
  666. SpMemFree(MenuItems[i]);
  667. }
  668. SpMemFree(MenuItems);
  669. SpMemFree(MenuOrdinals);
  670. xx0:
  671. SpMemFree(PartitionPath);
  672. return(rc);
  673. }
  674. #if 0
  675. typedef
  676. VOID
  677. (*PINSTALLATION_CALLBACK_ROUTINE)(
  678. IN PWSTR DirectoryPath,
  679. IN PFILE_DIRECTORY_INFORMATION FoundFileInfo
  680. );
  681. //
  682. // Stuff to reduce stack usage.
  683. //
  684. PINSTALLATION_CALLBACK_ROUTINE FileIterationCallback;
  685. POBJECT_ATTRIBUTES FileIterationObja;
  686. PIO_STATUS_BLOCK FileIterationIoStatusBlock;
  687. PUNICODE_STRING FileIterationUnicodeString;
  688. VOID
  689. SpIterateInstallationFilesWorker(
  690. IN PWSTR FilenamePart1,
  691. IN PWSTR FilenamePart2
  692. )
  693. {
  694. PVOID InfoBuffer;
  695. PWSTR FullPath;
  696. NTSTATUS Status;
  697. HANDLE hFile;
  698. BOOLEAN restart;
  699. #define DIRINFO(x) ((PFILE_DIRECTORY_INFORMATION)InfoBuffer)
  700. InfoBuffer = SpMemAlloc(1024);
  701. //
  702. // Form the full path name of the current directory.
  703. //
  704. FullPath = SpMemAlloc( ( wcslen(FilenamePart1)
  705. + (FilenamePart2 ? wcslen(FilenamePart2) : 0),
  706. + 2) * sizeof(WCHAR)
  707. );
  708. wcscpy(FullPath,FilenamePart1);
  709. if(FilenamePart2) {
  710. SpConcatenatePaths(FullPath,FilenamePart2);
  711. }
  712. //
  713. // Open the directory for list access.
  714. //
  715. INIT_OBJA(FileIterationObja,FileIterationUnicodeString,FullPath);
  716. Status = ZwOpenFile(
  717. &hFile,
  718. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  719. FileIterationObja,
  720. FileIterationIoStatusBlock,
  721. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  722. FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
  723. );
  724. if(NT_SUCCESS(Status)) {
  725. restart = TRUE;
  726. do {
  727. Status = ZwQueryDirectoryFile(
  728. hFile,
  729. NULL,
  730. NULL,
  731. NULL,
  732. FileIterationIoStatusBlock,
  733. InfoBuffer,
  734. 1024 - sizeof(WCHAR), // leave room for nul
  735. FileDirectoryInformation,
  736. TRUE, // return single entry
  737. NULL, // no file name (match all files)
  738. restart
  739. );
  740. restart = FALSE;
  741. if(NT_SUCCESS(Status)) {
  742. //
  743. // nul-terminate the filename just in case
  744. //
  745. DIRINFO->FileName[DIRINFO->FileNameLength/sizeof(WCHAR)] = 0;
  746. if(DIRINFO->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  747. if(DIRINFO->FileName[0] != L'.') {
  748. SpIterateInstallationFiles(
  749. FullPath,
  750. DIRINFO->FileName
  751. );
  752. FileIterationCallback(FullPath,InfoBuffer);
  753. }
  754. } else {
  755. FileIterationCallback(FullPath,InfoBuffer);
  756. }
  757. }
  758. } while(NT_SUCCESS(Status));
  759. ZwClose(hFile);
  760. } else {
  761. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open directory %ws for list access (%lx)\n",FullPath,Status));
  762. }
  763. SpMemFree(FullPath);
  764. SpMemFree(InfoBuffer);
  765. }
  766. VOID
  767. SpIterateInstallationFiles(
  768. IN PWSTR FilenamePart1,
  769. IN PWSTR FilenamePart2,
  770. IN PINSTALLATION_CALLBACK_ROUTINE CallbackFunction
  771. )
  772. {
  773. //
  774. // Set up stack-saving globals
  775. //
  776. FileIterationIoStatusBlock = SpMemAlloc(sizeof(IO_STATUS_BLOCK);
  777. FileIterationUnicodeString = SpMemAlloc(sizeof(UNICODE_STRING));
  778. FileIterationObja = SpMemAlloc(sizeof(OBJECT_ATTRIBUTES);
  779. FileIterationCallback = CallbackFunction;
  780. //
  781. // Do the iteration.
  782. //
  783. SpIterateInstallationFilesWorker(FileNamePart1,FilenamePart2);
  784. //
  785. // Clean up.
  786. //
  787. SpMemFree(FileIterationObja);
  788. SpMemFree(FileIterationUnicodeString);
  789. SpMemFree(FileIterationIoStatusBlock);
  790. }
  791. #endif
  792. BOOLEAN
  793. IsSetupLogFormatNew(
  794. IN PVOID Inf
  795. )
  796. /*++
  797. Routine Description:
  798. Informs the caller whether or not the information on setup.log
  799. is in the new format.
  800. Arguments:
  801. Inf -
  802. Return Value:
  803. TRUE if the information is in the new format.
  804. FALSE otherwise.
  805. --*/
  806. {
  807. return( SpGetSectionKeyExists ( Inf,
  808. SIF_NEW_REPAIR_SIGNATURE,
  809. SIF_NEW_REPAIR_VERSION_KEY )
  810. );
  811. }