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.

1026 lines
27 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. #if defined(_AMD64_) || defined(_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 // defined(_AMD64_) || defined(_X86_)
  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,
  588. NtCount,
  589. FALSE,
  590. Keys,
  591. NULL,
  592. NULL,
  593. NULL,
  594. &key,
  595. &Choice);
  596. if(key == KEY_F3) {
  597. SpConfirmExit();
  598. } else if(key == ASCI_ESC) {
  599. break;
  600. } else if(key == ASCI_CR) {
  601. if(Choice == NtCount) {
  602. b = FALSE;
  603. } else {
  604. BOOLEAN keys;
  605. ULONG ValidKeys2[3] = { KEY_F3,ASCI_ESC,0 };
  606. //
  607. // User wants to actually remove an installation.
  608. // Confirm and then do that here.
  609. //
  610. redraw2:
  611. SpStartScreen(
  612. SP_SCRN_REMOVE_EXISTING_NT,
  613. 3,
  614. HEADER_HEIGHT+1,
  615. FALSE,
  616. FALSE,
  617. DEFAULT_ATTRIBUTE,
  618. MenuItems[Choice]
  619. );
  620. SpDisplayStatusOptions(
  621. DEFAULT_STATUS_ATTRIBUTE,
  622. SP_STAT_R_EQUALS_REMOVE_FILES,
  623. SP_STAT_ESC_EQUALS_CANCEL,
  624. SP_STAT_F3_EQUALS_EXIT,
  625. 0
  626. );
  627. keys = TRUE;
  628. while(keys) {
  629. switch(SpWaitValidKey(ValidKeys2,NULL,Mnemonics)) {
  630. case KEY_F3:
  631. SpConfirmExit();
  632. goto redraw2;
  633. case ASCI_ESC:
  634. keys = FALSE;
  635. break;
  636. default:
  637. //
  638. // Must be r=remove files.
  639. //
  640. *SpaceFreed = SpRemoveInstallation(
  641. Region,
  642. PartitionPath,
  643. NtDirectoryList[MenuOrdinals[Choice]]
  644. );
  645. rc = TRUE;
  646. SpStartScreen(
  647. SP_SCRN_DONE_REMOVING_EXISTING_NT,
  648. 4,
  649. HEADER_HEIGHT+3,
  650. FALSE,
  651. FALSE,
  652. DEFAULT_ATTRIBUTE,
  653. *SpaceFreed
  654. );
  655. SpDisplayStatusOptions(
  656. DEFAULT_STATUS_ATTRIBUTE,
  657. SP_STAT_ENTER_EQUALS_CONTINUE,
  658. 0
  659. );
  660. while(SpInputGetKeypress() != ASCI_CR) ;
  661. keys = FALSE;
  662. b = FALSE;
  663. break;
  664. }
  665. }
  666. }
  667. } else {
  668. goto nextkey;
  669. }
  670. } while(b);
  671. SpMnDestroy(Menu);
  672. xx1:
  673. for(i=0; i<=NtCount; i++) {
  674. SpMemFree(MenuItems[i]);
  675. }
  676. SpMemFree(MenuItems);
  677. SpMemFree(MenuOrdinals);
  678. xx0:
  679. SpMemFree(PartitionPath);
  680. return(rc);
  681. }
  682. #if 0
  683. typedef
  684. VOID
  685. (*PINSTALLATION_CALLBACK_ROUTINE)(
  686. IN PWSTR DirectoryPath,
  687. IN PFILE_DIRECTORY_INFORMATION FoundFileInfo
  688. );
  689. //
  690. // Stuff to reduce stack usage.
  691. //
  692. PINSTALLATION_CALLBACK_ROUTINE FileIterationCallback;
  693. POBJECT_ATTRIBUTES FileIterationObja;
  694. PIO_STATUS_BLOCK FileIterationIoStatusBlock;
  695. PUNICODE_STRING FileIterationUnicodeString;
  696. VOID
  697. SpIterateInstallationFilesWorker(
  698. IN PWSTR FilenamePart1,
  699. IN PWSTR FilenamePart2
  700. )
  701. {
  702. PVOID InfoBuffer;
  703. PWSTR FullPath;
  704. NTSTATUS Status;
  705. HANDLE hFile;
  706. BOOLEAN restart;
  707. #define DIRINFO(x) ((PFILE_DIRECTORY_INFORMATION)InfoBuffer)
  708. InfoBuffer = SpMemAlloc(1024);
  709. //
  710. // Form the full path name of the current directory.
  711. //
  712. FullPath = SpMemAlloc( ( wcslen(FilenamePart1)
  713. + (FilenamePart2 ? wcslen(FilenamePart2) : 0),
  714. + 2) * sizeof(WCHAR)
  715. );
  716. wcscpy(FullPath,FilenamePart1);
  717. if(FilenamePart2) {
  718. SpConcatenatePaths(FullPath,FilenamePart2);
  719. }
  720. //
  721. // Open the directory for list access.
  722. //
  723. INIT_OBJA(FileIterationObja,FileIterationUnicodeString,FullPath);
  724. Status = ZwOpenFile(
  725. &hFile,
  726. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  727. FileIterationObja,
  728. FileIterationIoStatusBlock,
  729. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  730. FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
  731. );
  732. if(NT_SUCCESS(Status)) {
  733. restart = TRUE;
  734. do {
  735. Status = ZwQueryDirectoryFile(
  736. hFile,
  737. NULL,
  738. NULL,
  739. NULL,
  740. FileIterationIoStatusBlock,
  741. InfoBuffer,
  742. 1024 - sizeof(WCHAR), // leave room for nul
  743. FileDirectoryInformation,
  744. TRUE, // return single entry
  745. NULL, // no file name (match all files)
  746. restart
  747. );
  748. restart = FALSE;
  749. if(NT_SUCCESS(Status)) {
  750. //
  751. // nul-terminate the filename just in case
  752. //
  753. DIRINFO->FileName[DIRINFO->FileNameLength/sizeof(WCHAR)] = 0;
  754. if(DIRINFO->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  755. if(DIRINFO->FileName[0] != L'.') {
  756. SpIterateInstallationFiles(
  757. FullPath,
  758. DIRINFO->FileName
  759. );
  760. FileIterationCallback(FullPath,InfoBuffer);
  761. }
  762. } else {
  763. FileIterationCallback(FullPath,InfoBuffer);
  764. }
  765. }
  766. } while(NT_SUCCESS(Status));
  767. ZwClose(hFile);
  768. } else {
  769. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open directory %ws for list access (%lx)\n",FullPath,Status));
  770. }
  771. SpMemFree(FullPath);
  772. SpMemFree(InfoBuffer);
  773. }
  774. VOID
  775. SpIterateInstallationFiles(
  776. IN PWSTR FilenamePart1,
  777. IN PWSTR FilenamePart2,
  778. IN PINSTALLATION_CALLBACK_ROUTINE CallbackFunction
  779. )
  780. {
  781. //
  782. // Set up stack-saving globals
  783. //
  784. FileIterationIoStatusBlock = SpMemAlloc(sizeof(IO_STATUS_BLOCK);
  785. FileIterationUnicodeString = SpMemAlloc(sizeof(UNICODE_STRING));
  786. FileIterationObja = SpMemAlloc(sizeof(OBJECT_ATTRIBUTES);
  787. FileIterationCallback = CallbackFunction;
  788. //
  789. // Do the iteration.
  790. //
  791. SpIterateInstallationFilesWorker(FileNamePart1,FilenamePart2);
  792. //
  793. // Clean up.
  794. //
  795. SpMemFree(FileIterationObja);
  796. SpMemFree(FileIterationUnicodeString);
  797. SpMemFree(FileIterationIoStatusBlock);
  798. }
  799. #endif
  800. BOOLEAN
  801. IsSetupLogFormatNew(
  802. IN PVOID Inf
  803. )
  804. /*++
  805. Routine Description:
  806. Informs the caller whether or not the information on setup.log
  807. is in the new format.
  808. Arguments:
  809. Inf -
  810. Return Value:
  811. TRUE if the information is in the new format.
  812. FALSE otherwise.
  813. --*/
  814. {
  815. return( SpGetSectionKeyExists ( Inf,
  816. SIF_NEW_REPAIR_SIGNATURE,
  817. SIF_NEW_REPAIR_VERSION_KEY )
  818. );
  819. }