diff --git a/.msvc/rufus_2010.vcxproj b/.msvc/rufus_2010.vcxproj
index 25bfc3f9..fde20c6f 100644
--- a/.msvc/rufus_2010.vcxproj
+++ b/.msvc/rufus_2010.vcxproj
@@ -80,6 +80,7 @@
_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions)
MultiThreadedDebug
Level3
+ ..\inc;%(AdditionalIncludeDirectories)
setupapi.lib;comctl32.lib;%(AdditionalDependencies)
@@ -95,7 +96,7 @@
X64
- ..\..\msvc;..\..\libwdi;%(AdditionalIncludeDirectories)
+ ..\inc;%(AdditionalIncludeDirectories)
_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions)
MultiThreadedDebug
Level3
@@ -115,6 +116,7 @@
_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions)
MultiThreaded
Level3
+ ..\inc;%(AdditionalIncludeDirectories)
setupapi.lib;comctl32.lib;%(AdditionalDependencies)
@@ -133,6 +135,7 @@
_CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions)
MultiThreaded
Level3
+ ..\inc;%(AdditionalIncludeDirectories)
setupapi.lib;comctl32.lib;%(AdditionalDependencies)
@@ -143,11 +146,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.msvc/rufus_2010.vcxproj.filters b/.msvc/rufus_2010.vcxproj.filters
index dc7c559d..03dee667 100644
--- a/.msvc/rufus_2010.vcxproj.filters
+++ b/.msvc/rufus_2010.vcxproj.filters
@@ -13,6 +13,9 @@
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav
+
+ {ecff9fec-41c4-4ce8-b725-27ee39754cb7}
+
@@ -24,6 +27,21 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -41,6 +59,99 @@
Header Files
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
+
+ Header Files\inc
+
diff --git a/_pre-commit.sh b/_pre-commit.sh
index 6a809c3c..ed4694d4 100644
--- a/_pre-commit.sh
+++ b/_pre-commit.sh
@@ -39,10 +39,13 @@ mv cmd.sed~ cmd.sed
# Run sed to update the nano version
# NB: we need to run git add else the modified files may be ignored
sed -f cmd.sed ./rufus.rc > ./rufus.rc~
-mv ./rufus.rc~ ./rufus.rc
+# MinGW's sed has the bad habit of eating CRLFs
+sed 's/$/\r/' ./rufus.rc~ > ./rufus.rc
+rm ./rufus.rc~
git add ./rufus.rc
sed -f cmd.sed ./rufus.h > ./rufus.h~
-mv ./rufus.h~ ./rufus.h
+sed 's/$/\r/' ./rufus.h~ > ./rufus.h
+rm ./rufus.h~
git add ./rufus.h
#sed -f cmd.sed _bm.sh > _bm.sh~
#mv _bm.sh~ _bm.sh
diff --git a/license.h b/license.h
index 407d561a..498e6e7f 100644
--- a/license.h
+++ b/license.h
@@ -26,6 +26,10 @@ const char* additional_copyrights =
"http://pcunleashed.com\r\n"
"Freeware\r\n"
"\r\n"
+"Boot record handling by ms-sys by Henrik Carlqvist:\r\n"
+"http://ms-sys.sourceforge.net\r\n"
+"GNU General Public License (GPL) v2 or later\r\n"
+"\r\n"
"FS Type description from by GNU fdisk:\r\n"
"http://www.gnu.org/software/fdisk\r\n"
"GNU General Public License (GPL) v3 or later\r\n"
diff --git a/rufus.c b/rufus.c
index 4b197209..81e31cfb 100644
--- a/rufus.c
+++ b/rufus.c
@@ -37,6 +37,7 @@
#include
#include
#include
+#include
// http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c
// http://ms-sys.sourceforge.net/
@@ -47,6 +48,9 @@
#include "resource.h"
#include "rufus.h"
#include "sys_types.h"
+#include "br.h"
+#include "fat32.h"
+#include "file.h"
#if !defined(GUID_DEVINTERFACE_DISK)
const GUID GUID_DEVINTERFACE_DISK = { 0x53f56307L, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b} };
@@ -110,8 +114,38 @@ void _uprintf(const char *format, ...)
}
#endif
+void DumpBufferHex(unsigned char *buffer, size_t size)
+{
+ size_t i, j, k, pos;
+ char line[80] = "";
-void StatusPrintf(const char *format, ...)
+ for (i=0, pos=0; i 126)) {
+ sprintf(&line[strlen(line)], ".");
+ } else {
+ sprintf(&line[strlen(line)], "%c", buffer[i+j]);
+ }
+ }
+ }
+ }
+ uprintf("%s\n", line);
+}
+
+void PrintStatus(const char *format, ...)
{
char buf[256], *p = buf;
va_list args;
@@ -146,81 +180,104 @@ static const char* GetPartitionType(BYTE Type)
}
/*
- * Open a drive with optional write access - return a drive HANDLE and the drive letter
+ * Open a drive with optional write access - returns a drive HANDLE and the drive letter
+ * or INVALID_HANDLE_VALUE (/!\ which is != NULL /!\) on failure
* This call is quite risky (left unchecked, inadvertently passing 0 as index would
* return a handle to C:, which we might then proceed to unknowingly repartition!),
* so we apply the following mitigation factors:
* - Valid indexes must belong to a specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX]
* - When opening for write access, we lock the volume. If that fails, which would
- * typically be the case on C:\ or any other drive in use, we fail the call
+ * typically be the case on C:\ or any other drive in use, we report failure
* - We report the full path of any drive that was successfully opened for write acces
*/
-static BOOL GetDriveHandle(DWORD DriveIndex, HANDLE* hDrive, char* DriveLetter, BOOL bWriteAccess)
+static HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive)
{
BOOL r;
DWORD size;
+ HANDLE hDrive = INVALID_HANDLE_VALUE;
STORAGE_DEVICE_NUMBER_REDEF device_number = {0};
char drives[26*4]; /* "D:\", "E:\", etc. */
char *drive = drives;
- char drive_name[] = "\\\\.\\#:";
+ char logical_drive[] = "\\\\.\\#:";
+ char physical_drive[24];
if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) {
- uprintf("WARNING: Bad index value. Please check your code!\n");
+ uprintf("WARNING: Bad index value. Please check the code!\n");
}
DriveIndex -= DRIVE_INDEX_MIN;
- size = GetLogicalDriveStringsA(sizeof(drives), drives);
- if (size == 0) {
- uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString());
- return FALSE;
- }
- if (size > sizeof(drives)) {
- uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives));
- return FALSE;
- }
-
- *hDrive = INVALID_HANDLE_VALUE;
- for ( ;*drive; drive += safe_strlen(drive)+1) {
- if (!isalpha(*drive))
- continue;
- *drive = (char)toupper((int)*drive);
- if (*drive < 'C') {
- continue;
- }
- safe_sprintf(drive_name, sizeof(drive_name), "\\\\.\\%c:", drive[0]);
- *hDrive = CreateFileA(drive_name, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
+ // If no drive letter is requested, open a phyical drive
+ if (DriveLetter == NULL) {
+ safe_sprintf(physical_drive, sizeof(physical_drive), "\\\\.\\PHYSICALDRIVE%d", DriveIndex);
+ hDrive = CreateFileA(physical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDrive == INVALID_HANDLE_VALUE) {
- uprintf("Could not open drive %c: %s\n", drive[0], WindowsErrorString());
- continue;
+ uprintf("Could not open drive %s: %s\n", physical_drive, WindowsErrorString());
+ goto out;
+ }
+ if (bWriteAccess) {
+ uprintf("Caution: Opened %s drive for write access\n", physical_drive);
+ }
+ } else {
+ *DriveLetter = ' ';
+ size = GetLogicalDriveStringsA(sizeof(drives), drives);
+ if (size == 0) {
+ uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString());
+ goto out;
+ }
+ if (size > sizeof(drives)) {
+ uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives));
+ goto out;
}
- r = DeviceIoControl(*hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL,
- 0, &device_number, sizeof(device_number), &size, NULL);
- if ((!r) || (size <= 0)) {
- uprintf("IOCTL_STORAGE_GET_DEVICE_NUMBER (GetDriveHandle) failed: %s\n", WindowsErrorString());
- safe_closehandle(*hDrive);
- break;
- }
- if (device_number.DeviceNumber == DriveIndex) {
- if (bWriteAccess) {
- if (!DeviceIoControl(*hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL)) {
- uprintf("Could not get exclusive access to %s: %s\n", drive_name, WindowsErrorString());
- safe_closehandle(*hDrive);
- return FALSE;
- }
- uprintf("Caution: Opened %s drive for write access\n", drive_name);
+ hDrive = INVALID_HANDLE_VALUE;
+ for ( ;*drive; drive += safe_strlen(drive)+1) {
+ if (!isalpha(*drive))
+ continue;
+ *drive = (char)toupper((int)*drive);
+ if (*drive < 'C') {
+ continue;
+ }
+ safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]);
+ hDrive = CreateFileA(logical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
+ FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+ if (hDrive == INVALID_HANDLE_VALUE) {
+ uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString());
+ continue;
}
- break;
- }
- safe_closehandle(*hDrive);
- }
- if (DriveLetter != NULL) {
+ r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL,
+ 0, &device_number, sizeof(device_number), &size, NULL);
+ if ((!r) || (size <= 0)) {
+ uprintf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed for device %s: %s\n", logical_drive, WindowsErrorString());
+ } else if (device_number.DeviceNumber == DriveIndex) {
+ break;
+ }
+ safe_closehandle(hDrive);
+ }
+ if (hDrive == INVALID_HANDLE_VALUE) {
+ goto out;
+ }
+ if (bWriteAccess) {
+ uprintf("Caution: Opened %s drive for write access\n", logical_drive);
+ }
*DriveLetter = *drive?*drive:' ';
}
- return (*hDrive != INVALID_HANDLE_VALUE);
+ if ((bLockDrive) && (!DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))) {
+ uprintf("Could not get exclusive access to %s: %s\n", logical_drive, WindowsErrorString());
+ safe_closehandle(hDrive);
+ goto out;
+ }
+
+out:
+ return hDrive;
+}
+
+static __inline BOOL UnlockDrive(HANDLE hDrive)
+{
+ DWORD size;
+ return DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL);
}
/*
@@ -234,7 +291,8 @@ static BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label)
*label = STR_NO_LABEL;
- if (!GetDriveHandle(DriveIndex, &hDrive, DrivePath, FALSE))
+ hDrive = GetDriveHandle(DriveIndex, DrivePath, FALSE, FALSE);
+ if (hDrive == INVALID_HANDLE_VALUE)
return FALSE;
safe_closehandle(hDrive);
*letter = DrivePath[0];
@@ -250,7 +308,7 @@ static void SetClusterSizes(enum _FSType FSType)
{
IGNORE_RETVAL(ComboBox_ResetContent(hClusterSize));
// Don't ask me - just following the MS standard here
- IGNORE_RETVAL(ComboBox_SetItemData(hClusterSize, ComboBox_AddStringU(hClusterSize, "Default allocation size"), 0x8000));
+ IGNORE_RETVAL(ComboBox_SetItemData(hClusterSize, ComboBox_AddStringU(hClusterSize, "Default allocation size"), 0x1000));
// TODO set value above according to FS selected and default cluster sizes from
// http://support.microsoft.com/kb/140365
IGNORE_RETVAL(ComboBox_SetItemData(hClusterSize, ComboBox_AddStringU(hClusterSize, "512 bytes"), 0x200));
@@ -292,7 +350,8 @@ static BOOL GetDriveInfo(void)
SelectedDrive.DiskSize = 0;
- if (!GetDriveHandle(SelectedDrive.DeviceNumber, &hDrive, DrivePath, FALSE))
+ hDrive = GetDriveHandle(SelectedDrive.DeviceNumber, DrivePath, FALSE, FALSE);
+ if (hDrive == INVALID_HANDLE_VALUE)
return FALSE;
r = DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
@@ -436,54 +495,6 @@ static BOOL PopulateProperties(int ComboIndex)
return TRUE;
}
-static BOOL WriteSectors(HANDLE hDrive, size_t SectorSize, size_t StartSector, size_t nSectors, void* Buf, size_t BufSize)
-{
- LARGE_INTEGER ptr;
- DWORD Size;
-
- if (SectorSize * nSectors > BufSize) {
- uprintf("WriteSectors: Buffer is too small\n");
- return FALSE;
- }
-
- ptr.QuadPart = StartSector*SectorSize;
- if (!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN)) {
- uprintf("WriteSectors: Could not access sector %lld - %s\n", StartSector, WindowsErrorString());
- return FALSE;
- }
-
- if ((!WriteFile(hDrive, Buf, (DWORD)BufSize, &Size, NULL)) || (Size != BufSize)) {
- uprintf("WriteSectors: Write error - %s\n", WindowsErrorString());
- return FALSE;
- }
-
- return TRUE;
-}
-
-static BOOL ReadSectors(HANDLE hDrive, size_t SectorSize, size_t StartSector, size_t nSectors, void* Buf, size_t BufSize)
-{
- LARGE_INTEGER ptr;
- DWORD size;
-
- if (SectorSize * nSectors > BufSize) {
- uprintf("ReadSectors: Buffer is too small\n");
- return FALSE;
- }
-
- ptr.QuadPart = StartSector*SectorSize;
- if (!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN)) {
- uprintf("ReadSectors: Could not access sector %lld - %s\n", StartSector, WindowsErrorString());
- return FALSE;
- }
-
- if ((!ReadFile(hDrive, Buf, (DWORD)BufSize, &size, NULL)) || (size != BufSize)) {
- uprintf("ReadSectors: Write error - %s\n", WindowsErrorString());
- return FALSE;
- }
-
- return TRUE;
-}
-
/*
* Create a partition table
*/
@@ -494,7 +505,7 @@ static BOOL CreatePartition(HANDLE hDrive)
BOOL r;
DWORD size;
- StatusPrintf("Partitioning...");
+ PrintStatus("Partitioning...");
DriveLayoutEx->PartitionStyle = PARTITION_STYLE_MBR;
DriveLayoutEx->PartitionCount = 4; // Must be multiple of 4 for MBR
DriveLayoutEx->Mbr.Signature = GetTickCount();
@@ -508,13 +519,13 @@ static BOOL CreatePartition(HANDLE hDrive)
DriveLayoutEx->PartitionEntry[0].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack;
switch (ComboBox_GetCurSel(hFileSystem)) {
case FS_FAT16:
- DriveLayoutEx->PartitionEntry[0].Mbr.PartitionType = 0x0e;
+ DriveLayoutEx->PartitionEntry[0].Mbr.PartitionType = 0x0e; // FAT16 LBA
break;
case FS_NTFS:
- DriveLayoutEx->PartitionEntry[0].Mbr.PartitionType = 0x07;
+ DriveLayoutEx->PartitionEntry[0].Mbr.PartitionType = 0x07; // NTFS
break;
default:
- DriveLayoutEx->PartitionEntry[0].Mbr.PartitionType = 0x0c;
+ DriveLayoutEx->PartitionEntry[0].Mbr.PartitionType = 0x0c; // FAT32 LBA
break;
}
// For the remaining partitions, PartitionStyle & PartitionType have already
@@ -617,7 +628,7 @@ static BOOL FormatDrive(char DriveLetter)
WCHAR wLabel[128];
wDriveRoot[0] = (WCHAR)DriveLetter;
- StatusPrintf("Formatting...");
+ PrintStatus("Formatting...");
PF_INIT_OR_OUT(FormatEx, fmifs);
// TODO: properly set MediaType
@@ -636,41 +647,125 @@ out:
}
/*
- * Create a separate thread for the formatting operation
+ * Process the MBR
+ */
+static BOOL ProcessMBR(HANDLE hPhysicalDrive)
+{
+ BOOL r = FALSE;
+ HANDLE hDrive = hPhysicalDrive;
+ FILE fake_fd;
+ unsigned char* buf;
+ size_t SecSize = SelectedDrive.Geometry.BytesPerSector;
+ size_t nSecs = 0x200/min(0x200, SelectedDrive.Geometry.BytesPerSector);
+
+ if (SecSize * nSecs != 0x200) {
+ uprintf("Seriously? A drive where sector size is not a power of 2?!?\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
+ goto out;
+ }
+
+ PrintStatus("Processing MBR...\n");
+
+ fake_fd._ptr = (char*)hPhysicalDrive;
+ fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector;
+ uprintf("I'm %sa boot record\n", is_br(&fake_fd)?"":"NOT ");
+
+ // FormatEx rewrites the MBR and removes the LBA attribute of FAT16
+ // and FAT32 partitions - we need to correct this in the MBR
+ // TODO: something else for bootable GPT
+ buf = (unsigned char*)malloc(SecSize * nSecs);
+ if (buf == NULL) {
+ uprintf("Could not allocate memory for MBR");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY;
+ goto out;
+ }
+
+ if (!read_sectors(hDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) {
+ uprintf("Could not read MBR\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
+ goto out;
+ }
+ DumpBufferHex(buf, 0x200);
+ switch (ComboBox_GetCurSel(hFileSystem)) {
+ // TODO: check for 0x06 & 0x0b?
+ case FS_FAT16:
+ buf[0x1c2] = 0x0e;
+ break;
+ case FS_FAT32:
+ buf[0x1c2] = 0x0c;
+ break;
+ }
+
+ if (!write_sectors(hDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) {
+ uprintf("Could not write MBR\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
+ goto out;
+ }
+
+ r = TRUE;
+
+out:
+ safe_free(buf);
+ return r;
+}
+
+/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562%28v=vs.85%29.aspx
+ Dismounting a volume is useful when a volume needs to disappear for a while. For
+ example, an application that changes a volume file system from the FAT file system
+ to the NTFS file system might use the following procedure.
+
+ To change a volume file system
+
+ Open a volume.
+ Lock the volume.
+ Format the volume.
+ Dismount the volume.
+ Unlock the volume.
+ Close the volume handle.
+
+ A dismounting operation removes the volume from the FAT file system awareness.
+ When the operating system mounts the volume, it appears as an NTFS file system volume.
+*/
+
+/*
+ * Standalone thread for the formatting operation
*/
static void __cdecl FormatThread(void* param)
{
DWORD num = (DWORD)(uintptr_t)param;
- HANDLE hDrive;
- BOOL r;
+ HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
+ HANDLE hLogicalVolume = INVALID_HANDLE_VALUE;
char drive_name[] = "?:";
int i;
+// DWORD size;
- if (!GetDriveHandle(num, &hDrive, NULL, TRUE)) {
+ hPhysicalDrive = GetDriveHandle(num, NULL, TRUE, TRUE);
+ if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
goto out;
}
+ // At this stage with have both a handle and a lock to the physical drive
- r = CreatePartition(hDrive);
- safe_closehandle(hDrive);
- if (!r) {
+ if (!CreatePartition(hPhysicalDrive)) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
goto out;
}
- // Make sure we can reopen the drive before trying to format it
+ // Make sure we can access the volume again before trying to format it
for (i=0; i<10; i++) {
Sleep(500);
- if (GetDriveHandle(num, &hDrive, drive_name, FALSE)) {
+ hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE);
+ if (hLogicalVolume != INVALID_HANDLE_VALUE) {
break;
}
}
if (i >= 10) {
- uprintf("Unable to reopen drive post partitioning\n");
+ uprintf("Could not access volume after partitioning\n");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
goto out;
}
- safe_closehandle(hDrive);
+ // Handle needs to be closed for FormatEx to be happy - we keep a lock though
+ safe_closehandle(hLogicalVolume);
if (!FormatDrive(drive_name[0])) {
// Error will be set by FormatDrive() in FormatStatus
@@ -678,12 +773,47 @@ static void __cdecl FormatThread(void* param)
goto out;
}
+ // TODO: Enable compression on NTFS
+ // TODO: disable indexing on NTFS
+
+ // Ideally we would lock, FSCTL_DISMOUNT_VOLUME, unlock and close our volume
+ // handle, but some explorer versions have problems with volumes disappear
+// #define VOL_DISMOUNT
+#ifdef VOL_DISMOUNT
+ // Dismount the volume
+ hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE);
+ if (hLogicalVolume == INVALID_HANDLE_VALUE) {
+ uprintf("Could not open the volume for dismount\n");
+ goto out;
+ }
+
+ if (!DeviceIoControl(hLogicalVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &size, NULL)) {
+ uprintf("Could not dismount volume\n");
+ goto out;
+ }
+#endif
+ if (!ProcessMBR(hPhysicalDrive)) {
+ goto out;
+ }
+
+#ifdef VOL_DISMOUNT
+ safe_unlockclose(hLogicalVolume);
+// Sleep(10000);
+ hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, FALSE);
+ if (hLogicalVolume == INVALID_HANDLE_VALUE) {
+ uprintf("Could not re-mount volume\n");
+ goto out;
+ }
+#endif
+
if (IsChecked(IDC_DOSSTARTUP)) {
// TODO: check return value & set bootblock
ExtractMSDOS(drive_name);
}
out:
+ safe_unlockclose(hLogicalVolume);
+ safe_unlockclose(hPhysicalDrive);
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
_endthread();
}
@@ -794,7 +924,7 @@ static BOOL GetUSBDevices(void)
}
}
IGNORE_RETVAL(ComboBox_SetCurSel(hDeviceList, 0));
- PostMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_DEVICE, 0);
+ SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_DEVICE, 0);
return TRUE;
}
@@ -805,7 +935,7 @@ static void EnableControls(BOOL bEnable)
EnableWindow(GetDlgItem(hMainDialog, IDC_DEVICE), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_CAPACITY), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_FILESYSTEM), bEnable);
- EnableWindow(GetDlgItem(hMainDialog, IDC_ALLOCSIZE), bEnable);
+ EnableWindow(GetDlgItem(hMainDialog, IDC_CLUSTERSIZE), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_LABEL), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_QUICKFORMAT), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_DOSSTARTUP), bEnable);
@@ -888,7 +1018,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
// Operation may have completed in the meantime
if (format_thid != -1L) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
- StatusPrintf("Cancelling - please wait...");
+ PrintStatus("Cancelling - please wait...");
}
}
return (INT_PTR)TRUE;
@@ -905,7 +1035,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case IDC_DEVICE:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
- StatusPrintf("%d device%s found.", ComboBox_GetCount(hDeviceList),
+ PrintStatus("%d device%s found.", ComboBox_GetCount(hDeviceList),
(ComboBox_GetCount(hDeviceList)!=1)?"s":"");
PopulateProperties(ComboBox_GetCurSel(hDeviceList));
break;
@@ -968,9 +1098,10 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
SendMessage(hProgress, PBM_SETRANGE, 0, 100<<16);
}
SendMessage(hProgress, PBM_SETPOS, FormatStatus?0:100, 0);
- StatusPrintf(!IS_ERROR(FormatStatus)?"DONE":
- ((SCODE_CODE(FormatStatus)==ERROR_CANCELLED)?"Cancelled":"FAILED"));
EnableControls(TRUE);
+ GetUSBDevices();
+ PrintStatus(!IS_ERROR(FormatStatus)?"DONE":
+ ((SCODE_CODE(FormatStatus)==ERROR_CANCELLED)?"Cancelled":"FAILED"));
return (INT_PTR)TRUE;
}
return (INT_PTR)FALSE;
diff --git a/rufus.h b/rufus.h
index cbda2c17..3da6c8e8 100644
--- a/rufus.h
+++ b/rufus.h
@@ -22,7 +22,7 @@
#define RUFUS_DEBUG
-#define APP_VERSION "Rufus v1.0.0.44"
+#define APP_VERSION "Rufus v1.0.0.45"
#define STR_NO_LABEL "NO_LABEL"
#define RUFUS_CANCELBOX_TITLE "Rufus - Cancellation"
#define DRIVE_INDEX_MIN 0x80
diff --git a/rufus.rc b/rufus.rc
index 41b77fa4..327f6388 100644
Binary files a/rufus.rc and b/rufus.rc differ