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