diff --git a/.msvc/rufus_2010.vcxproj b/.msvc/rufus_2010.vcxproj
index d670e00d..6097ddb6 100644
--- a/.msvc/rufus_2010.vcxproj
+++ b/.msvc/rufus_2010.vcxproj
@@ -151,12 +151,14 @@
+
+
diff --git a/.msvc/rufus_2010.vcxproj.filters b/.msvc/rufus_2010.vcxproj.filters
index a3f2a847..2a2450ef 100644
--- a/.msvc/rufus_2010.vcxproj.filters
+++ b/.msvc/rufus_2010.vcxproj.filters
@@ -45,6 +45,9 @@
Source Files
+
+ Source Files
+
@@ -146,6 +149,9 @@
Header Files\inc
+
+ Header Files
+
diff --git a/.msvc/rufus_sources b/.msvc/rufus_sources
index 9f2d4014..b8c41b0a 100644
--- a/.msvc/rufus_sources
+++ b/.msvc/rufus_sources
@@ -23,13 +23,14 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \
# http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/
SXS_APPLICATION_MANIFEST=common_controls_and_elevation.manifest
-SOURCES=rufus.c \
- stdio.c \
- stdlg.c \
- msdos.c \
- file.c \
- br.c \
- fat12.c \
- fat16.c \
- fat32.c \
+SOURCES=rufus.c \
+ format.c \
+ stdio.c \
+ stdlg.c \
+ msdos.c \
+ file.c \
+ br.c \
+ fat12.c \
+ fat16.c \
+ fat32.c \
rufus.rc
diff --git a/Makefile b/Makefile
index ae7c4075..9a30f9b2 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@
# along with this program; if not, see .
#
-OBJECTS = fat12.o fat16.o fat32.o br.o file.o msdos.o stdio.o stdlg.o rufus.o
+OBJECTS = fat12.o fat16.o fat32.o br.o file.o msdos.o format.o stdio.o stdlg.o rufus.o
TARGET = rufus
CC = gcc
diff --git a/format.c b/format.c
new file mode 100644
index 00000000..cd0fa291
--- /dev/null
+++ b/format.c
@@ -0,0 +1,435 @@
+/*
+ * Rufus: The Resourceful USB Formatting Utility
+ * Formatting function calls
+ * Copyright (c) 2011 Pete Batard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifdef _CRTDBG_MAP_ALLOC
+#include
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+// #include
+
+#include "msapi_utf8.h"
+#include "rufus.h"
+#include "resource.h"
+#include "br.h"
+#include "fat16.h"
+#include "fat32.h"
+#include "file.h"
+#include "format.h"
+
+/*
+ * FormatEx callback. Return FALSE to halt operations
+ */
+static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Action, PVOID pData)
+{
+ DWORD* percent;
+ int task_number = 0;
+
+ if (IS_ERROR(FormatStatus))
+ return FALSE;
+
+ switch(Command) {
+ case FCC_PROGRESS:
+ percent = (DWORD*)pData;
+ PostMessage(hMainDialog, UM_FORMAT_PROGRESS, (WPARAM)*percent, (LPARAM)0);
+ uprintf("%d percent completed.\n", *percent);
+ break;
+ case FCC_STRUCTURE_PROGRESS: // No progress on quick format
+ uprintf("Format task %d/? completed.\n", ++task_number);
+ break;
+ case FCC_DONE:
+ if(*(BOOLEAN*)pData == FALSE) {
+ uprintf("Error while formatting.\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE;
+ }
+ break;
+ case FCC_DONE_WITH_STRUCTURE: // We get this message when formatting Small FAT16
+ // pData Seems to be a struct with at least one (32 BIT!!!) string pointer to the size in MB
+ uprintf("Done with that sort of things: Action=%d pData=%0p\n", Action, pData);
+ DumpBufferHex(pData, 8);
+ uprintf("Volume size: %s MB\n", (char*)(LONG_PTR)(*(ULONG32*)pData));
+ break;
+ case FCC_INCOMPATIBLE_FILE_SYSTEM:
+ uprintf("Incompatible File System\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INCOMPATIBLE_FS;
+ break;
+ case FCC_ACCESS_DENIED:
+ uprintf("Access denied\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
+ break;
+ case FCC_MEDIA_WRITE_PROTECTED:
+ uprintf("Media is write protected\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_PROTECT;
+ break;
+ case FCC_VOLUME_IN_USE:
+ uprintf("Volume is in use\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_DEVICE_IN_USE;
+ break;
+ case FCC_CANT_QUICK_FORMAT:
+ uprintf("Cannot quick format this volume\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANT_QUICK_FORMAT;
+ break;
+ case FCC_BAD_LABEL:
+ uprintf("Bad label\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_LABEL_TOO_LONG;
+ break;
+ case FCC_OUTPUT:
+ uprintf("%s\n", ((PTEXTOUTPUT)pData)->Output);
+ break;
+ case FCC_CLUSTER_SIZE_TOO_BIG:
+ case FCC_CLUSTER_SIZE_TOO_SMALL:
+ uprintf("Unsupported cluster size\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_CLUSTER_SIZE;
+ break;
+ case FCC_VOLUME_TOO_BIG:
+ case FCC_VOLUME_TOO_SMALL:
+ uprintf("Volume is too %s\n", FCC_VOLUME_TOO_BIG?"big":"small");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_VOLUME_SIZE;
+ case FCC_NO_MEDIA_IN_DRIVE:
+ uprintf("No media in drive\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_MEDIA_IN_DRIVE;
+ break;
+ default:
+ uprintf("FormatExCallback: received unhandled command %X\n", Command);
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
+ break;
+ }
+ return (!IS_ERROR(FormatStatus));
+}
+
+/*
+ * Call on fmifs.dll's FormatEx() to format the drive
+ */
+static BOOL FormatDrive(char DriveLetter)
+{
+ BOOL r = FALSE;
+ PF_DECL(FormatEx);
+ WCHAR wDriveRoot[] = L"?:\\";
+ WCHAR wFSType[32];
+ WCHAR wLabel[128];
+ size_t i;
+
+ wDriveRoot[0] = (WCHAR)DriveLetter;
+ PrintStatus("Formatting...");
+ PF_INIT_OR_OUT(FormatEx, fmifs);
+
+ // TODO: properly set MediaType
+ GetWindowTextW(hFileSystem, wFSType, ARRAYSIZE(wFSType));
+ // We may have a " (Default)" trail
+ for (i=0; i= 10) {
+ uprintf("Could not access volume after partitioning\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
+ goto out;
+ }
+ // 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
+ uprintf("Format error: 0x%08X\n", FormatStatus);
+ goto out;
+ }
+
+ // TODO: Enable compression on NTFS
+ // TODO: optionally disable indexing on NTFS
+ // TODO: use progress bar during MBR/FSBR/MSDOS copy
+
+ // 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
+ PrintStatus("Writing master boot record...\n");
+ if (!ProcessMBR(hPhysicalDrive)) {
+ // Errorcode has already been set
+ 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)) {
+ hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE);
+ if (hLogicalVolume == INVALID_HANDLE_VALUE) {
+ uprintf("Could not re-mount volume\n");
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
+ goto out;
+ }
+ PrintStatus("Writing filesystem boot record...\n");
+ if (!ProcessFS_BR(hLogicalVolume)) {
+ // Errorcode has already been set
+ goto out;
+ }
+ PrintStatus("Copying MS-DOS files...\n");
+ if (!ExtractMSDOS(drive_name)) {
+ FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
+ goto out;
+ }
+ }
+
+out:
+ safe_unlockclose(hLogicalVolume);
+ safe_unlockclose(hPhysicalDrive);
+ PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
+ _endthread();
+}
diff --git a/format.h b/format.h
new file mode 100644
index 00000000..9a56ed6d
--- /dev/null
+++ b/format.h
@@ -0,0 +1,106 @@
+/*
+ * Rufus: The Resourceful USB Formatting Utility
+ * Formatting function calls
+ * Copyright (c) 2011 Pete Batard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include // for MEDIA_TYPE
+
+#pragma once
+
+/*
+ * typedefs for the function prototypes. Use the something like:
+ * PF_DECL(FormatEx);
+ * which translates to:
+ * FormatEx_t pfFormatEx = NULL;
+ * in your code, to declare the entrypoint and then use:
+ * PF_INIT(FormatEx, fmifs);
+ * which translates to:
+ * pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx");
+ * to make it accessible.
+ */
+static __inline HMODULE GetDLLHandle(char* szDLLName)
+{
+ HMODULE h = NULL;
+ if ((h = GetModuleHandleA(szDLLName)) == NULL)
+ h = LoadLibraryA(szDLLName);
+ return h;
+}
+#define PF_DECL(proc) proc##_t pf##proc = NULL
+#define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc)
+#define PF_INIT_OR_OUT(proc, dllname) \
+ PF_INIT(proc, dllname); if (pf##proc == NULL) { \
+ uprintf("unable to access %s DLL: %s", #dllname, \
+ WindowsErrorString()); goto out; }
+
+/* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their
+ designation from msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
+typedef enum {
+ FCC_PROGRESS,
+ FCC_DONE_WITH_STRUCTURE,
+ FCC_UNKNOWN2,
+ FCC_INCOMPATIBLE_FILE_SYSTEM,
+ FCC_UNKNOWN4,
+ FCC_UNKNOWN5,
+ FCC_ACCESS_DENIED,
+ FCC_MEDIA_WRITE_PROTECTED,
+ FCC_VOLUME_IN_USE,
+ FCC_CANT_QUICK_FORMAT,
+ FCC_UNKNOWNA,
+ FCC_DONE,
+ FCC_BAD_LABEL,
+ FCC_UNKNOWND,
+ FCC_OUTPUT,
+ FCC_STRUCTURE_PROGRESS,
+ FCC_CLUSTER_SIZE_TOO_SMALL,
+ FCC_CLUSTER_SIZE_TOO_BIG,
+ FCC_VOLUME_TOO_SMALL,
+ FCC_VOLUME_TOO_BIG,
+ FCC_NO_MEDIA_IN_DRIVE,
+} FILE_SYSTEM_CALLBACK_COMMAND;
+
+typedef struct {
+ DWORD Lines;
+ CHAR* Output;
+} TEXTOUTPUT, *PTEXTOUTPUT;
+
+typedef BOOLEAN (__stdcall *FILE_SYSTEM_CALLBACK)(
+ FILE_SYSTEM_CALLBACK_COMMAND Command,
+ ULONG Action,
+ PVOID pData
+);
+
+/* Parameter names aligned to
+ http://msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
+typedef VOID (WINAPI *FormatEx_t)(
+ WCHAR* DriveRoot,
+ MEDIA_TYPE MediaType, // See WinIoCtl.h
+ WCHAR* FileSystemTypeName,
+ WCHAR* Label,
+ BOOL QuickFormat,
+ ULONG DesiredUnitAllocationSize,
+ FILE_SYSTEM_CALLBACK Callback
+);
+
+/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa383357.aspx */
+typedef enum {
+ FPF_COMPRESSED = 0x01
+} FILE_SYSTEM_PROP_FLAG;
+
+typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)(
+ WCHAR* DriveRoot,
+ ULONG CompressionFlags // FILE_SYSTEM_PROP_FLAG
+);
diff --git a/msapi_utf8.h b/msapi_utf8.h
index 68233f01..2833c626 100644
--- a/msapi_utf8.h
+++ b/msapi_utf8.h
@@ -25,6 +25,8 @@
#include
#include
+#pragma once
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/rufus.c b/rufus.c
index 12dbe844..c4b1f859 100644
--- a/rufus.c
+++ b/rufus.c
@@ -40,26 +40,20 @@
#include
// http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c
-// http://ms-sys.sourceforge.net/
// http://thestarman.pcministry.com/asm/mbr/MSWIN41.htm
-// http://www.c-jump.com/CIS24/Slides/FAT/lecture.html#F01_0130_sector_assignments
#include "msapi_utf8.h"
#include "resource.h"
#include "rufus.h"
#include "sys_types.h"
-#include "br.h"
-#include "fat16.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} };
#endif
-const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "exFAT" };
+static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "exFAT" };
// Don't ask me - just following the MS standard here
-const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes","4096 bytes","8192 bytes",
+static const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes","4096 bytes","8192 bytes",
"16 kilobytes", "32 kilobytes", "64 kilobytes", "128 kilobytes", "256 kilobytes", "512 kilobytes",
"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" };
@@ -81,27 +75,14 @@ HWND hStatus;
float fScale = 1.0f;
int default_fs;
ULONG default_clutersize;
-
+RUFUS_DRIVE_INFO SelectedDrive;
BOOL bBootable;
BOOL bQuickFormat;
-
-struct {
- DWORD DeviceNumber;
- LONGLONG DiskSize;
- DISK_GEOMETRY Geometry;
- DWORD FirstSector;
- int FSType;
- struct {
- ULONG Allowed;
- ULONG Default;
- } ClusterSize[FS_MAX];
-} SelectedDrive;
-
-static HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel;
+DWORD FormatStatus;
+HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel;
static HWND hDeviceTooltip = NULL, hFSTooltip = NULL;
-static StrArray DriveID, DriveLabel;
-static DWORD FormatStatus;
+static StrArray DriveID, DriveLabel;
/*
* Convert a partition type to its human readable form using
@@ -119,7 +100,7 @@ static const char* GetPartitionType(BYTE Type)
/*
* Open a drive with optional write access - returns a drive HANDLE and the drive letter
- * or INVALID_HANDLE_VALUE (/!\ which is != NULL /!\) on failure
+ * or INVALID_HANDLE_VALUE (/!\ which is DIFFERENT from 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:
@@ -128,7 +109,7 @@ static const char* GetPartitionType(BYTE Type)
* 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 HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive)
+HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive)
{
BOOL r;
DWORD size;
@@ -212,12 +193,6 @@ out:
return hDrive;
}
-static __inline BOOL UnlockDrive(HANDLE hDrive)
-{
- DWORD size;
- return DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL);
-}
-
/*
* Return the drive letter and volume label
*/
@@ -242,12 +217,10 @@ static BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label)
return TRUE;
}
-
#define KB 1024LL
#define MB 1048576LL
#define GB 1073741824LL
#define TB 1099511627776LL
-
/*
* Set cluster size values according to http://support.microsoft.com/kb/140365
* this call will return FALSE if we can't find a supportable FS for the drive
@@ -559,7 +532,7 @@ static BOOL PopulateProperties(int ComboIndex)
/*
* Create a partition table
*/
-static BOOL CreatePartition(HANDLE hDrive)
+BOOL CreatePartition(HANDLE hDrive)
{
BYTE layout[sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 3*sizeof(PARTITION_INFORMATION_EX)] = {0};
PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)layout;
@@ -605,402 +578,6 @@ static BOOL CreatePartition(HANDLE hDrive)
return TRUE;
}
-/*
- * FormatEx callback. Return FALSE to halt operations
- */
-static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Action, PVOID pData)
-{
- DWORD* percent;
- int task_number = 0;
-
- if (IS_ERROR(FormatStatus))
- return FALSE;
-
- switch(Command) {
- case FCC_PROGRESS:
- percent = (DWORD*)pData;
- PostMessage(hMainDialog, UM_FORMAT_PROGRESS, (WPARAM)*percent, (LPARAM)0);
- uprintf("%d percent completed.\n", *percent);
- break;
- case FCC_STRUCTURE_PROGRESS: // No progress on quick format
- uprintf("Format task %d/? completed.\n", ++task_number);
- break;
- case FCC_DONE:
- if(*(BOOLEAN*)pData == FALSE) {
- uprintf("Error while formatting.\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE;
- }
- break;
- case FCC_DONE_WITH_STRUCTURE: // We get this message when formatting Small FAT16
- // pData Seems to be a struct with at least one (32 BIT!!!) string pointer to the size in MB
- uprintf("Done with that sort of things: Action=%d pData=%0p\n", Action, pData);
- DumpBufferHex(pData, 8);
- uprintf("Volume size: %s MB\n", (char*)(LONG_PTR)(*(ULONG32*)pData));
- break;
- case FCC_INCOMPATIBLE_FILE_SYSTEM:
- uprintf("Incompatible File System\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INCOMPATIBLE_FS;
- break;
- case FCC_ACCESS_DENIED:
- uprintf("Access denied\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
- break;
- case FCC_MEDIA_WRITE_PROTECTED:
- uprintf("Media is write protected\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_PROTECT;
- break;
- case FCC_VOLUME_IN_USE:
- uprintf("Volume is in use\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_DEVICE_IN_USE;
- break;
- case FCC_CANT_QUICK_FORMAT:
- uprintf("Cannot quick format this volume\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANT_QUICK_FORMAT;
- break;
- case FCC_BAD_LABEL:
- uprintf("Bad label\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_LABEL_TOO_LONG;
- break;
- case FCC_OUTPUT:
- uprintf("%s\n", ((PTEXTOUTPUT)pData)->Output);
- break;
- case FCC_CLUSTER_SIZE_TOO_BIG:
- case FCC_CLUSTER_SIZE_TOO_SMALL:
- uprintf("Unsupported cluster size\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_CLUSTER_SIZE;
- break;
- case FCC_VOLUME_TOO_BIG:
- case FCC_VOLUME_TOO_SMALL:
- uprintf("Volume is too %s\n", FCC_VOLUME_TOO_BIG?"big":"small");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_VOLUME_SIZE;
- case FCC_NO_MEDIA_IN_DRIVE:
- uprintf("No media in drive\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_MEDIA_IN_DRIVE;
- break;
- default:
- uprintf("FormatExCallback: received unhandled command %X\n", Command);
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
- break;
- }
- return (!IS_ERROR(FormatStatus));
-}
-
-/*
- * Call on fmifs.dll's FormatEx() to format the drive
- */
-static BOOL FormatDrive(char DriveLetter)
-{
- BOOL r = FALSE;
- PF_DECL(FormatEx);
- WCHAR wDriveRoot[] = L"?:\\";
- WCHAR wFSType[32];
- WCHAR wLabel[128];
- size_t i;
-
- wDriveRoot[0] = (WCHAR)DriveLetter;
- PrintStatus("Formatting...");
- PF_INIT_OR_OUT(FormatEx, fmifs);
-
- // TODO: properly set MediaType
- GetWindowTextW(hFileSystem, wFSType, ARRAYSIZE(wFSType));
- // We may have a " (Default)" trail
- for (i=0; i= 10) {
- uprintf("Could not access volume after partitioning\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
- goto out;
- }
- // 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
- uprintf("Format error: 0x%08X\n", FormatStatus);
- goto out;
- }
-
- // TODO: Enable compression on NTFS
- // TODO: optionally disable indexing on NTFS
- // TODO: use progress bar during MBR/FSBR/MSDOS copy
-
- // 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
- PrintStatus("Writing master boot record...\n");
- if (!ProcessMBR(hPhysicalDrive)) {
- // Errorcode has already been set
- 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)) {
- hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE);
- if (hLogicalVolume == INVALID_HANDLE_VALUE) {
- uprintf("Could not re-mount volume\n");
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
- goto out;
- }
- PrintStatus("Writing filesystem boot record...\n");
- if (!ProcessFS_BR(hLogicalVolume)) {
- // Errorcode has already been set
- goto out;
- }
- PrintStatus("Copying MS-DOS files...\n");
- if (!ExtractMSDOS(drive_name)) {
- FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
- goto out;
- }
- }
-
-out:
- safe_unlockclose(hLogicalVolume);
- safe_unlockclose(hPhysicalDrive);
- PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
- _endthread();
-}
-
/*
* Refresh the list of USB devices
*/
diff --git a/rufus.h b/rufus.h
index 86ce3201..970927a8 100644
--- a/rufus.h
+++ b/rufus.h
@@ -15,8 +15,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-#include
-#include // for MEDIA_TYPE
+#include
+#include // for DISK_GEOMETRY
#pragma once
@@ -62,42 +62,6 @@
#define safe_vsnprintf vsnprintf
#endif
-/*
- * Globals
- */
-extern HINSTANCE hMainInstance;
-extern HWND hMainDialog;
-extern HWND hStatus;
-extern float fScale;
-extern char szFolderPath[MAX_PATH];
-
-/*
- * Shared prototypes
- */
-extern char *WindowsErrorString(void);
-extern void DumpBufferHex(void *buf, size_t size);
-extern void PrintStatus(const char *format, ...);
-extern void CenterDialog(HWND hDlg);
-extern void CreateStatusBar(void);
-extern INT_PTR CreateAboutBox(void);
-extern HWND CreateTooltip(HWND hControl, const char* message, int duration);
-extern void DestroyTooltip(HWND hWnd);
-extern void DestroyAllTooltips(void);
-extern void Notification(int type, char* text, char* title);
-extern BOOL ExtractMSDOS(const char* path);
-
-/* Basic String Array */
-typedef struct {
- char** Table;
- size_t Size;
- size_t Index;
- size_t Max;
-} StrArray;
-extern void StrArrayCreate(StrArray* arr, size_t initial_size);
-extern void StrArrayAdd(StrArray* arr, const char* str);
-extern void StrArrayClear(StrArray* arr);
-extern void StrArrayDestroy(StrArray* arr);
-
#ifdef RUFUS_DEBUG
extern void _uprintf(const char *format, ...);
#define uprintf(...) _uprintf(__VA_ARGS__)
@@ -131,95 +95,73 @@ enum {
FS_MAX
};
+/* Current drive info */
+typedef struct {
+ DWORD DeviceNumber;
+ LONGLONG DiskSize;
+ DISK_GEOMETRY Geometry;
+ DWORD FirstSector;
+ int FSType;
+ struct {
+ ULONG Allowed;
+ ULONG Default;
+ } ClusterSize[FS_MAX];
+} RUFUS_DRIVE_INFO;
+
+/*
+ * Globals
+ */
+extern HINSTANCE hMainInstance;
+extern HWND hMainDialog, hStatus, hDeviceList, hCapacity;
+extern HWND hFileSystem, hClusterSize, hLabel;
+extern float fScale;
+extern char szFolderPath[MAX_PATH];
+extern DWORD FormatStatus;
+extern RUFUS_DRIVE_INFO SelectedDrive;
+
+/*
+ * Shared prototypes
+ */
+extern char *WindowsErrorString(void);
+extern void DumpBufferHex(void *buf, size_t size);
+extern void PrintStatus(const char *format, ...);
+extern void CenterDialog(HWND hDlg);
+extern void CreateStatusBar(void);
+extern INT_PTR CreateAboutBox(void);
+extern HWND CreateTooltip(HWND hControl, const char* message, int duration);
+extern void DestroyTooltip(HWND hWnd);
+extern void DestroyAllTooltips(void);
+extern void Notification(int type, char* text, char* title);
+extern BOOL ExtractMSDOS(const char* path);
+extern void __cdecl FormatThread(void* param);
+extern BOOL CreatePartition(HANDLE hDrive);
+extern HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive);
+
+__inline static BOOL UnlockDrive(HANDLE hDrive)
+{
+ DWORD size;
+ return DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL);
+}
+
+/* Basic String Array */
+typedef struct {
+ char** Table;
+ size_t Size;
+ size_t Index;
+ size_t Max;
+} StrArray;
+extern void StrArrayCreate(StrArray* arr, size_t initial_size);
+extern void StrArrayAdd(StrArray* arr, const char* str);
+extern void StrArrayClear(StrArray* arr);
+extern void StrArrayDestroy(StrArray* arr);
+
+/* We need a redef of this MS structure */
typedef struct {
DWORD DeviceType;
ULONG DeviceNumber;
ULONG PartitionNumber;
} STORAGE_DEVICE_NUMBER_REDEF;
-/*
- * typedefs for the function prototypes. Use the something like:
- * PF_DECL(FormatEx);
- * which translates to:
- * FormatEx_t pfFormatEx = NULL;
- * in your code, to declare the entrypoint and then use:
- * PF_INIT(FormatEx, fmifs);
- * which translates to:
- * pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx");
- * to make it accessible.
- */
-static __inline HMODULE GetDLLHandle(char* szDLLName)
-{
- HMODULE h = NULL;
- if ((h = GetModuleHandleA(szDLLName)) == NULL)
- h = LoadLibraryA(szDLLName);
- return h;
-}
-#define PF_DECL(proc) proc##_t pf##proc = NULL
-#define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc)
-#define PF_INIT_OR_OUT(proc, dllname) \
- PF_INIT(proc, dllname); if (pf##proc == NULL) { \
- uprintf("unable to access %s DLL: %s", #dllname, \
- WindowsErrorString()); goto out; }
-
-/* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their
- designation from msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
-typedef enum {
- FCC_PROGRESS,
- FCC_DONE_WITH_STRUCTURE,
- FCC_UNKNOWN2,
- FCC_INCOMPATIBLE_FILE_SYSTEM,
- FCC_UNKNOWN4,
- FCC_UNKNOWN5,
- FCC_ACCESS_DENIED,
- FCC_MEDIA_WRITE_PROTECTED,
- FCC_VOLUME_IN_USE,
- FCC_CANT_QUICK_FORMAT,
- FCC_UNKNOWNA,
- FCC_DONE,
- FCC_BAD_LABEL,
- FCC_UNKNOWND,
- FCC_OUTPUT,
- FCC_STRUCTURE_PROGRESS,
- FCC_CLUSTER_SIZE_TOO_SMALL,
- FCC_CLUSTER_SIZE_TOO_BIG,
- FCC_VOLUME_TOO_SMALL,
- FCC_VOLUME_TOO_BIG,
- FCC_NO_MEDIA_IN_DRIVE,
-} FILE_SYSTEM_CALLBACK_COMMAND;
-
-typedef struct {
- DWORD Lines;
- CHAR* Output;
-} TEXTOUTPUT, *PTEXTOUTPUT;
-
-typedef BOOLEAN (__stdcall *FILE_SYSTEM_CALLBACK)(
- FILE_SYSTEM_CALLBACK_COMMAND Command,
- ULONG Action,
- PVOID pData
-);
-
-/* Parameter names aligned to
- http://msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
-typedef VOID (WINAPI *FormatEx_t)(
- WCHAR* DriveRoot,
- MEDIA_TYPE MediaType, // See WinIoCtl.h
- WCHAR* FileSystemTypeName,
- WCHAR* Label,
- BOOL QuickFormat,
- ULONG DesiredUnitAllocationSize,
- FILE_SYSTEM_CALLBACK Callback
-);
-
-/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa383357.aspx */
-typedef enum {
- FPF_COMPRESSED = 0x01
-} FILE_SYSTEM_PROP_FLAG;
-
-typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)(
- WCHAR* DriveRoot,
- ULONG CompressionFlags // FILE_SYSTEM_PROP_FLAG
-);
/* Custom application errors */
#define FAC(f) (f<<16)
diff --git a/rufus.rc b/rufus.rc
index 0f2e96d6..3790baf5 100644
--- a/rufus.rc
+++ b/rufus.rc
@@ -63,7 +63,7 @@ BEGIN
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
CONTROL "https://github.com/pbatard/rufus",IDC_ABOUT_RUFUS_URL,
"SysLink",WS_TABSTOP,46,47,114,9
- LTEXT "Version 1.0.0 (Build 57)",IDC_STATIC,46,19,78,8
+ LTEXT "Version 1.0.0 (Build 58)",IDC_STATIC,46,19,78,8
PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP
EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL
LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8
@@ -162,8 +162,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,57
- PRODUCTVERSION 1,0,0,57
+ FILEVERSION 1,0,0,58
+ PRODUCTVERSION 1,0,0,58
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -180,13 +180,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "akeo.ie"
VALUE "FileDescription", "Rufus"
- VALUE "FileVersion", "1.0.0.57"
+ VALUE "FileVersion", "1.0.0.58"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
- VALUE "ProductVersion", "1.0.0.57"
+ VALUE "ProductVersion", "1.0.0.58"
END
END
BLOCK "VarFileInfo"
@@ -212,7 +212,7 @@ IDI_ICON ICON "rufus.ico"
STRINGTABLE
BEGIN
- IDS_VERSION "Rufus v1.0.0.57"
+ IDS_VERSION "Rufus v1.0.0.58"
END
#endif // English resources
diff --git a/stdio.c b/stdio.c
index e13f8af7..b28f621b 100644
--- a/stdio.c
+++ b/stdio.c
@@ -16,6 +16,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+#ifdef _CRTDBG_MAP_ALLOC
+#include
+#include
+#endif
#include
#include