From d81ca7de24cd61282d0bf9232257782d6792de5b Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Fri, 5 Jul 2013 22:20:46 +0100 Subject: [PATCH] [core] reinstate the call to DeletePartitions() * But use IOCTL_DISK_CREATE_DISK and not IOCTL_DISK_DELETE_DRIVE_LAYOUT * Also improve messaging and increase detection timeout to 15 seconds --- src/drive.c | 32 ++++++++++++++++++++++++++++++++ src/format.c | 30 ++++++++++++++++++++---------- src/rufus.h | 4 ++-- src/rufus.rc | 10 +++++----- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/drive.c b/src/drive.c index 87964a96..f673a408 100644 --- a/src/drive.c +++ b/src/drive.c @@ -579,6 +579,10 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m } break; case PARTITION_STYLE_GPT: + // TODO: (?) As per MSDN: "When specifying a GUID partition table (GPT) as the PARTITION_STYLE of the CREATE_DISK + // structure, an application should wait for the MSR partition arrival before sending the IOCTL_DISK_SET_DRIVE_LAYOUT_EX + // control code. For more information about device notification, see RegisterDeviceNotification." + CreateDisk.PartitionStyle = PARTITION_STYLE_GPT; IGNORE_RETVAL(CoCreateGuid(&CreateDisk.Gpt.DiskId)); CreateDisk.Gpt.MaxPartitionCount = MAX_GPT_PARTITIONS; @@ -676,6 +680,34 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m return TRUE; } +/* Delete the disk partition table */ +BOOL DeletePartitions(HANDLE hDrive) +{ + BOOL r; + DWORD size; + CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}}; + + PrintStatus(0, TRUE, "Deleting partitions..."); + + size = sizeof(CreateDisk); + r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK, + (BYTE*)&CreateDisk, size, NULL, 0, &size, NULL ); + if (!r) { + uprintf("Could not delete drive layout: %s\n", WindowsErrorString()); + safe_closehandle(hDrive); + return FALSE; + } + + r = DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &size, NULL ); + if (!r) { + uprintf("Could not refresh drive layout: %s\n", WindowsErrorString()); + safe_closehandle(hDrive); + return FALSE; +} + +return TRUE; +} + /* * Convert a partition type to its human readable form using * (slightly modified) entries from GNU fdisk diff --git a/src/format.c b/src/format.c index e7dc2316..aee94141 100644 --- a/src/format.c +++ b/src/format.c @@ -576,9 +576,9 @@ static BOOL FormatFAT32(DWORD DriveIndex) // Set the FAT32 volume label GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel)); ToValidLabel(wLabel, TRUE); + PrintStatus(0, TRUE, "Setting Label (This may take while)..."); // Handle must be closed for SetVolumeLabel to work safe_closehandle(hLogicalVolume); - PrintStatus(0, TRUE, "Setting Label (This may take while)..."); VolumeName = GetLogicalName(DriveIndex, TRUE, TRUE); wVolumeName = utf8_to_wchar(VolumeName); if ((wVolumeName == NULL) || (!SetVolumeLabelW(wVolumeName, wLabel))) { @@ -708,22 +708,22 @@ static BOOL AnalyzeMBR(HANDLE hPhysicalDrive) return FALSE; } if (is_dos_mbr(&fake_fd)) { - uprintf("Drive has a Microsoft DOS/NT/95A master boot record\n"); + uprintf("Drive has a DOS/NT/95A master boot record\n"); } else if (is_dos_f2_mbr(&fake_fd)) { - uprintf("Drive has a Microsoft DOS/NT/95A master boot record " + uprintf("Drive has a DOS/NT/95A master boot record " "with the undocumented F2 instruction\n"); } else if (is_95b_mbr(&fake_fd)) { - uprintf("Drive has a Microsoft 95B/98/98SE/ME master boot record\n"); + uprintf("Drive has a Windows 95B/98/98SE/ME master boot record\n"); } else if (is_2000_mbr(&fake_fd)) { - uprintf("Drive has a Microsoft 2000/XP/2003 master boot record\n"); + uprintf("Drive has a Windows 2000/XP/2003 master boot record\n"); } else if (is_vista_mbr(&fake_fd)) { - uprintf("Drive has a Microsoft Vista master boot record\n"); + uprintf("Drive has a Windows Vista master boot record\n"); } else if (is_win7_mbr(&fake_fd)) { - uprintf("Drive has a Microsoft 7 master boot record\n"); + uprintf("Drive has a Windows 7 master boot record\n"); } else if (is_zero_mbr(&fake_fd)) { uprintf("Drive has a zeroed non-bootable master boot record\n"); } else { - uprintf("Unknown boot record\n"); + uprintf("Drive has an unknown master boot record\n"); } return TRUE; } @@ -753,6 +753,8 @@ static BOOL AnalyzePBR(HANDLE hLogicalVolume) } else { uprintf("Drive has an unknown FAT16 or FAT32 partition boot record\n"); } + } else { + uprintf("Drive has an unknown partition boot record\n"); } return TRUE; } @@ -1260,11 +1262,19 @@ DWORD WINAPI FormatThread(LPVOID param) PrintStatus(0, TRUE, "Analyzing existing boot records...\n"); AnalyzeMBR(hPhysicalDrive); - if (hLogicalVolume != NULL) { + if ((hLogicalVolume != NULL) && (hLogicalVolume != INVALID_HANDLE_VALUE)) { AnalyzePBR(hLogicalVolume); } UpdateProgress(OP_ANALYZE_MBR, -1.0f); + // Zap any existing partitions. This helps prevent access errors. + // As this creates issues with FAT16 formatted MS drives, only do this for other filesystems + if ( (fs != FS_FAT16) && (!DeletePartitions(hPhysicalDrive)) ) { + uprintf("Could not reset partitions\n"); + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE; + goto out; + } + if (IsChecked(IDC_BADBLOCKS)) { do { // create a log file for bad blocks report. Since %USERPROFILE% may @@ -1325,7 +1335,7 @@ DWORD WINAPI FormatThread(LPVOID param) } } // Close the (unmounted) volume before formatting - if (hLogicalVolume != NULL) { + if ((hLogicalVolume != NULL) && (hLogicalVolume != INVALID_HANDLE_VALUE)) { PrintStatus(0, TRUE, "Closing existing volume...\n"); if (!CloseHandle(hLogicalVolume)) { uprintf("Could not close volume: %s\n", WindowsErrorString()); diff --git a/src/rufus.h b/src/rufus.h index fe0ba328..d4d1e026 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -36,8 +36,8 @@ #define STR_NO_LABEL "NO_LABEL" #define RUFUS_CANCELBOX_TITLE APPLICATION_NAME " - Cancellation" #define RUFUS_BLOCKING_IO_TITLE APPLICATION_NAME " - Flushing buffers" -#define DRIVE_ACCESS_TIMEOUT 10000 // How long we should retry drive access (in ms) -#define DRIVE_ACCESS_RETRIES 20 // How many times we should retry +#define DRIVE_ACCESS_TIMEOUT 15000 // How long we should retry drive access (in ms) +#define DRIVE_ACCESS_RETRIES 60 // How many times we should retry #define DRIVE_INDEX_MIN 0x00000080 #define DRIVE_INDEX_MAX 0x000000C0 #define MAX_DRIVES (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN) diff --git a/src/rufus.rc b/src/rufus.rc index d63f4ba2..78324a31 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -30,7 +30,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.3.4.264" +CAPTION "Rufus v1.3.4.265" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,291,50,14 @@ -278,8 +278,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,4,264 - PRODUCTVERSION 1,3,4,264 + FILEVERSION 1,3,4,265 + PRODUCTVERSION 1,3,4,265 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -296,13 +296,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.3.4.264" + VALUE "FileVersion", "1.3.4.265" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2013 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.3.4.264" + VALUE "ProductVersion", "1.3.4.265" END END BLOCK "VarFileInfo"