1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2024-08-14 23:57:05 +00:00

[core] added formatting

* also added filter for hotplug detection
This commit is contained in:
Pete Batard 2011-11-26 00:25:04 +00:00
parent 7280b0c45b
commit 1c302ee594
3 changed files with 246 additions and 11 deletions

View file

@ -30,6 +30,11 @@ const char* additional_copyrights =
"http://www.gnu.org/software/fdisk\r\n" "http://www.gnu.org/software/fdisk\r\n"
"GNU General Public License (GPL) v3 or later\r\n" "GNU General Public License (GPL) v3 or later\r\n"
"\r\n" "\r\n"
"fmifs.dll usage based on Formatx by Mark Russinovich:\r\n"
"http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/source/fmifs.shtml\r\n"
"http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/fmifs\r\n"
"Public Domain\r\n"
"\r\n"
"About and License dialogs inspired by WinSCP\r\n" "About and License dialogs inspired by WinSCP\r\n"
"Copyright (c) 2000-2011 Martin Prikryl\r\n" "Copyright (c) 2000-2011 Martin Prikryl\r\n"
"GNU General Public License (GPL) v3 or later"; "GNU General Public License (GPL) v3 or later";

159
rufus.c
View file

@ -35,12 +35,9 @@
#include <commctrl.h> #include <commctrl.h>
#include <setupapi.h> #include <setupapi.h>
#include <winioctl.h> #include <winioctl.h>
#include <dbt.h>
// http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/source/fmifs.shtml
// http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/fmifs/
//#include <fmifs.h>
// http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c // http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c
// http://ms-sys.sourceforge.net/ // http://ms-sys.sourceforge.net/
// http://thestarman.pcministry.com/asm/mbr/MSWIN41.htm // http://thestarman.pcministry.com/asm/mbr/MSWIN41.htm
@ -77,6 +74,7 @@ struct {
static HWND hDeviceList, hCapacity, hFileSystem, hLabel; static HWND hDeviceList, hCapacity, hFileSystem, hLabel;
static HWND hDeviceTooltip = NULL, hFSTooltip = NULL; static HWND hDeviceTooltip = NULL, hFSTooltip = NULL;
static StrArray DriveID, DriveLabel; static StrArray DriveID, DriveLabel;
static DWORD FormatErr;
#ifdef RUFUS_DEBUG #ifdef RUFUS_DEBUG
void _uprintf(const char *format, ...) void _uprintf(const char *format, ...)
@ -282,12 +280,12 @@ static BOOL GetDriveInfo(void)
if (DriveLayout->PartitionEntry[i].Mbr.PartitionType != PARTITION_ENTRY_UNUSED) { if (DriveLayout->PartitionEntry[i].Mbr.PartitionType != PARTITION_ENTRY_UNUSED) {
uprintf("Partition #%d:\n", ++nb_partitions); uprintf("Partition #%d:\n", ++nb_partitions);
if (hFSTooltip == NULL) { if (hFSTooltip == NULL) {
safe_sprintf(tmp, sizeof(tmp), "Current file system: %s (0x%02X)", safe_sprintf(tmp, sizeof(tmp), "Current file system: %s (0x%02x)",
GetPartitionType(DriveLayout->PartitionEntry[i].Mbr.PartitionType), GetPartitionType(DriveLayout->PartitionEntry[i].Mbr.PartitionType),
DriveLayout->PartitionEntry[i].Mbr.PartitionType); DriveLayout->PartitionEntry[i].Mbr.PartitionType);
hFSTooltip = CreateTooltip(hFileSystem, tmp, -1); hFSTooltip = CreateTooltip(hFileSystem, tmp, -1);
} }
uprintf(" Type: %s (0x%02X)\n Boot: %s\n Recognized: %s\n Hidden Sectors: %d\n", uprintf(" Type: %s (0x%02x)\n Boot: %s\n Recognized: %s\n Hidden Sectors: %d\n",
GetPartitionType(DriveLayout->PartitionEntry[i].Mbr.PartitionType), GetPartitionType(DriveLayout->PartitionEntry[i].Mbr.PartitionType),
DriveLayout->PartitionEntry[i].Mbr.PartitionType, DriveLayout->PartitionEntry[i].Mbr.PartitionType,
DriveLayout->PartitionEntry[i].Mbr.BootIndicator?"Yes":"No", DriveLayout->PartitionEntry[i].Mbr.BootIndicator?"Yes":"No",
@ -452,6 +450,7 @@ BOOL CreatePartition(HANDLE hDrive)
BOOL r; BOOL r;
DWORD size; DWORD size;
StatusPrintf("Partitioning...");
DriveLayoutEx->PartitionStyle = PARTITION_STYLE_MBR; DriveLayoutEx->PartitionStyle = PARTITION_STYLE_MBR;
DriveLayoutEx->PartitionCount = 4; // Must be multiple of 4 for MBR DriveLayoutEx->PartitionCount = 4; // Must be multiple of 4 for MBR
DriveLayoutEx->Mbr.Signature = GetTickCount(); DriveLayoutEx->Mbr.Signature = GetTickCount();
@ -484,15 +483,126 @@ BOOL CreatePartition(HANDLE hDrive)
safe_closehandle(hDrive); safe_closehandle(hDrive);
return FALSE; return FALSE;
} }
StatusPrintf("Successfully Created Partition");
return TRUE; return TRUE;
} }
/*
* FormatEx callback. Return FALSE to halt operations
*/
BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Action, PVOID Data)
{
DWORD* percent;
int task_number = 0;
switch(Command) {
case FCC_PROGRESS:
percent = (DWORD*)Data;
// 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/n completed.\n", ++task_number);
break;
case FCC_DONE:
if(*(BOOLEAN*)Data == FALSE) {
uprintf("Error while formatting.\n");
if (FormatErr == 0)
FormatErr = FCC_DONE;
}
break;
case FCC_INCOMPATIBLE_FILE_SYSTEM:
uprintf("Incompatible File System\n");
FormatErr = Command;
break;
case FCC_ACCESS_DENIED:
uprintf("Access denied\n");
FormatErr = Command;
break;
case FCC_MEDIA_WRITE_PROTECTED:
uprintf("Media is write protected\n");
FormatErr = Command;
break;
case FCC_VOLUME_IN_USE:
uprintf("Volume is in use\n");
FormatErr = Command;
break;
case FCC_CANT_QUICK_FORMAT:
uprintf("Cannot quick format this volume\n");
FormatErr = Command;
break;
case FCC_BAD_LABEL:
uprintf("Bad label\n");
break;
case FCC_OUTPUT:
uprintf("%s\n", ((PTEXTOUTPUT)Data)->Output);
break;
case FCC_CLUSTER_SIZE_TOO_SMALL:
uprintf("Allocation unit size is too small\n");
FormatErr = Command;
break;
case FCC_CLUSTER_SIZE_TOO_BIG:
uprintf("Allocation unit size is too big\n");
FormatErr = Command;
break;
case FCC_VOLUME_TOO_SMALL:
uprintf("Volume is too small\n");
FormatErr = Command;
break;
case FCC_VOLUME_TOO_BIG:
uprintf("Volume is too big\n");
FormatErr = Command;
break;
case FCC_NO_MEDIA_IN_DRIVE:
uprintf("No media\n");
FormatErr = Command;
break;
default:
uprintf("FormatExCallback: received unhandled command %X\n", Command);
break;
}
return (FormatErr == 0);
}
BOOL Format(char DriveLetter)
{
BOOL r = FALSE;
PF_DECL(FormatEx);
WCHAR wDriveRoot[] = L"?:\\";
WCHAR wFSType[32];
WCHAR wLabel[128];
wDriveRoot[0] = (WCHAR)DriveLetter;
StatusPrintf("Formatting...");
PF_INIT_OR_OUT(FormatEx, fmifs);
// TODO: properly set MediaType
FormatErr = 0;
GetWindowText(hFileSystem, wFSType, ARRAYSIZE(wFSType));
GetWindowText(hLabel, wLabel, ARRAYSIZE(wLabel));
pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel,
(IsDlgButtonChecked(hMainDialog, IDC_QUICKFORMAT) == BST_CHECKED),
4096, FormatExCallback);
if (FormatErr == 0) {
uprintf("Format completed.\n");
StatusPrintf("Done.");
r = TRUE;
} else {
uprintf("Format error: %X\n", FormatErr);
StatusPrintf("FAILED.");
}
out:
return r;
}
// TODO: create a thread for this
BOOL FormatDrive(DWORD num) BOOL FormatDrive(DWORD num)
{ {
HANDLE hDrive; HANDLE hDrive;
BOOL r; BOOL r = FALSE;
char drive_letter;
int i;
if (!GetDriveHandle(num, &hDrive, NULL, TRUE)) { if (!GetDriveHandle(num, &hDrive, NULL, TRUE)) {
// TODO: report an error for exclusive access // TODO: report an error for exclusive access
@ -500,8 +610,24 @@ BOOL FormatDrive(DWORD num)
} }
r = CreatePartition(hDrive); r = CreatePartition(hDrive);
safe_closehandle(hDrive);
if (!r) return FALSE;
// Make sure we can reopen the drive before trying to format it
for (i=0; i<10; i++) {
Sleep(500);
if (GetDriveHandle(num, &hDrive, &drive_letter, FALSE)) {
break;
}
}
if (i >= 10) {
uprintf("Unable to reopen drive after partitioning\n");
return FALSE;
}
safe_closehandle(hDrive);
r = Format(drive_letter);
CloseHandle(hDrive);
return r; return r;
} }
@ -629,8 +755,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
switch (message) { switch (message) {
case WM_DEVICECHANGE: case WM_DEVICECHANGE:
GetUSBDevices(); // TODO: also prevent detect during format
return (INT_PTR)TRUE; if ((wParam == DBT_DEVICEARRIVAL) || (wParam == DBT_DEVICEREMOVECOMPLETE)) {
GetUSBDevices();
return (INT_PTR)TRUE;
}
break;
case WM_INITDIALOG: case WM_INITDIALOG:
hMainDialog = hDlg; hMainDialog = hDlg;
@ -646,8 +776,11 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
CreateStatusBar(); CreateStatusBar();
// Display the version in the right area of the status bar // Display the version in the right area of the status bar
SendMessageA(GetDlgItem(hDlg, IDC_STATUS), SB_SETTEXTA, SBT_OWNERDRAW | 1, (LPARAM)APP_VERSION); SendMessageA(GetDlgItem(hDlg, IDC_STATUS), SB_SETTEXTA, SBT_OWNERDRAW | 1, (LPARAM)APP_VERSION);
// Create the string array
StrArrayCreate(&DriveID, MAX_DRIVES); StrArrayCreate(&DriveID, MAX_DRIVES);
StrArrayCreate(&DriveLabel, MAX_DRIVES); StrArrayCreate(&DriveLabel, MAX_DRIVES);
// Set the quick format checkbox
CheckDlgButton(hDlg, IDC_QUICKFORMAT, BST_CHECKED);
GetUSBDevices(); GetUSBDevices();
return (INT_PTR)TRUE; return (INT_PTR)TRUE;
@ -706,6 +839,10 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
PostQuitMessage(0); PostQuitMessage(0);
break; break;
case UM_FORMAT_PROGRESS:
uprintf("Got UM_FORMAT_PROGRESS with percent %d\n", (DWORD)wParam);
return (INT_PTR)TRUE;
} }
return (INT_PTR)FALSE; return (INT_PTR)FALSE;
} }

93
rufus.h
View file

@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <winioctl.h> // for MEDIA_TYPE
#pragma once #pragma once
@ -98,6 +99,12 @@ extern void _uprintf(const char *format, ...);
#define uprintf(...) #define uprintf(...)
#endif #endif
/* Custom Windows messages */
enum user_message_type {
UM_FORMAT_PROGRESS = WM_APP,
UM_FORMAT_COMPLETED
};
/* Custom notifications */ /* Custom notifications */
enum MessageType { enum MessageType {
MSG_INFO, MSG_INFO,
@ -106,6 +113,8 @@ enum MessageType {
}; };
/* File system indexes in our FS combobox */ /* File system indexes in our FS combobox */
// TODO: FormatEx should support "NTFS", "FAT", "FAT32", "UDF", and "EXFAT" as per
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx
enum _FSType { enum _FSType {
FS_FAT16 = 0, FS_FAT16 = 0,
FS_FAT32, FS_FAT32,
@ -118,3 +127,87 @@ typedef struct {
ULONG DeviceNumber; ULONG DeviceNumber;
ULONG PartitionNumber; ULONG PartitionNumber;
} STORAGE_DEVICE_NUMBER_REDEF; } 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 Data
);
/* Parameter naming 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
);