mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[core] improved error and cancellation handling
* return standard Windows error codes where possible * add custom error codes that follow the Windows error format * automatically close cancel MessageBox if the process completes
This commit is contained in:
parent
23b1f55338
commit
d6c66e0d09
2 changed files with 51 additions and 44 deletions
84
rufus.c
84
rufus.c
|
@ -84,7 +84,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;
|
static DWORD FormatStatus;
|
||||||
|
|
||||||
#ifdef RUFUS_DEBUG
|
#ifdef RUFUS_DEBUG
|
||||||
void _uprintf(const char *format, ...)
|
void _uprintf(const char *format, ...)
|
||||||
|
@ -209,7 +209,7 @@ static BOOL GetDriveHandle(DWORD DriveIndex, HANDLE* hDrive, char* DriveLetter,
|
||||||
safe_closehandle(*hDrive);
|
safe_closehandle(*hDrive);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
uprintf("Warning: Opening %s drive for write access\n", drive_name);
|
uprintf("Caution: Opened %s drive for write access\n", drive_name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ static BOOL GetDriveHandle(DWORD DriveIndex, HANDLE* hDrive, char* DriveLetter,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DriveLetter != NULL) {
|
if (DriveLetter != NULL) {
|
||||||
*DriveLetter = *drive?*drive:' '; // TODO: handle NUL char upstream
|
*DriveLetter = *drive?*drive:' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*hDrive != INVALID_HANDLE_VALUE);
|
return (*hDrive != INVALID_HANDLE_VALUE);
|
||||||
|
@ -293,6 +293,7 @@ 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) {
|
||||||
|
// TODO: provide all partitions FS on tooltip, not just the one
|
||||||
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);
|
||||||
|
@ -508,7 +509,8 @@ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command,
|
||||||
DWORD* percent;
|
DWORD* percent;
|
||||||
int task_number = 0;
|
int task_number = 0;
|
||||||
|
|
||||||
if (FormatErr != 0) return FALSE;
|
if (IS_ERROR(FormatStatus))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
switch(Command) {
|
switch(Command) {
|
||||||
case FCC_PROGRESS:
|
case FCC_PROGRESS:
|
||||||
|
@ -517,65 +519,60 @@ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command,
|
||||||
uprintf("%d percent completed.\n", *percent);
|
uprintf("%d percent completed.\n", *percent);
|
||||||
break;
|
break;
|
||||||
case FCC_STRUCTURE_PROGRESS: // No progress on quick format
|
case FCC_STRUCTURE_PROGRESS: // No progress on quick format
|
||||||
uprintf("format task %d/n completed.\n", ++task_number);
|
uprintf("Format task %d/? completed.\n", ++task_number);
|
||||||
break;
|
break;
|
||||||
case FCC_DONE:
|
case FCC_DONE:
|
||||||
if(*(BOOLEAN*)Data == FALSE) {
|
if(*(BOOLEAN*)Data == FALSE) {
|
||||||
uprintf("Error while formatting.\n");
|
uprintf("Error while formatting.\n");
|
||||||
FormatErr = FCC_DONE;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FCC_INCOMPATIBLE_FILE_SYSTEM:
|
case FCC_INCOMPATIBLE_FILE_SYSTEM:
|
||||||
uprintf("Incompatible File System\n");
|
uprintf("Incompatible File System\n");
|
||||||
FormatErr = Command;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INCOMPATIBLE_FS;
|
||||||
break;
|
break;
|
||||||
case FCC_ACCESS_DENIED:
|
case FCC_ACCESS_DENIED:
|
||||||
uprintf("Access denied\n");
|
uprintf("Access denied\n");
|
||||||
FormatErr = Command;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
|
||||||
break;
|
break;
|
||||||
case FCC_MEDIA_WRITE_PROTECTED:
|
case FCC_MEDIA_WRITE_PROTECTED:
|
||||||
uprintf("Media is write protected\n");
|
uprintf("Media is write protected\n");
|
||||||
FormatErr = Command;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_PROTECT;
|
||||||
break;
|
break;
|
||||||
case FCC_VOLUME_IN_USE:
|
case FCC_VOLUME_IN_USE:
|
||||||
uprintf("Volume is in use\n");
|
uprintf("Volume is in use\n");
|
||||||
FormatErr = Command;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_DEVICE_IN_USE;
|
||||||
break;
|
break;
|
||||||
case FCC_CANT_QUICK_FORMAT:
|
case FCC_CANT_QUICK_FORMAT:
|
||||||
uprintf("Cannot quick format this volume\n");
|
uprintf("Cannot quick format this volume\n");
|
||||||
FormatErr = Command;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANT_QUICK_FORMAT;
|
||||||
break;
|
break;
|
||||||
case FCC_BAD_LABEL:
|
case FCC_BAD_LABEL:
|
||||||
uprintf("Bad label\n");
|
uprintf("Bad label\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_LABEL;
|
||||||
break;
|
break;
|
||||||
case FCC_OUTPUT:
|
case FCC_OUTPUT:
|
||||||
uprintf("%s\n", ((PTEXTOUTPUT)Data)->Output);
|
uprintf("%s\n", ((PTEXTOUTPUT)Data)->Output);
|
||||||
break;
|
break;
|
||||||
case FCC_CLUSTER_SIZE_TOO_SMALL:
|
|
||||||
uprintf("Allocation unit size is too small\n");
|
|
||||||
FormatErr = Command;
|
|
||||||
break;
|
|
||||||
case FCC_CLUSTER_SIZE_TOO_BIG:
|
case FCC_CLUSTER_SIZE_TOO_BIG:
|
||||||
uprintf("Allocation unit size is too big\n");
|
case FCC_CLUSTER_SIZE_TOO_SMALL:
|
||||||
FormatErr = Command;
|
uprintf("Allocation unit size is too %s\n", FCC_CLUSTER_SIZE_TOO_BIG?"big":"small");
|
||||||
break;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_CLUSTER_SIZE;
|
||||||
case FCC_VOLUME_TOO_SMALL:
|
|
||||||
uprintf("Volume is too small\n");
|
|
||||||
FormatErr = Command;
|
|
||||||
break;
|
break;
|
||||||
case FCC_VOLUME_TOO_BIG:
|
case FCC_VOLUME_TOO_BIG:
|
||||||
uprintf("Volume is too big\n");
|
case FCC_VOLUME_TOO_SMALL:
|
||||||
FormatErr = Command;
|
uprintf("Volume is too %s\n", FCC_VOLUME_TOO_BIG?"big":"small");
|
||||||
break;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_VOLUME_SIZE;
|
||||||
case FCC_NO_MEDIA_IN_DRIVE:
|
case FCC_NO_MEDIA_IN_DRIVE:
|
||||||
uprintf("No media\n");
|
uprintf("No media in drive\n");
|
||||||
FormatErr = Command;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_MEDIA_IN_DRIVE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
uprintf("FormatExCallback: received unhandled command %X\n", Command);
|
uprintf("FormatExCallback: received unhandled command %X\n", Command);
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (FormatErr == 0);
|
return (!IS_ERROR(FormatStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -594,17 +591,14 @@ static BOOL FormatDrive(char DriveLetter)
|
||||||
PF_INIT_OR_OUT(FormatEx, fmifs);
|
PF_INIT_OR_OUT(FormatEx, fmifs);
|
||||||
|
|
||||||
// TODO: properly set MediaType
|
// TODO: properly set MediaType
|
||||||
FormatErr = 0;
|
|
||||||
GetWindowTextW(hFileSystem, wFSType, ARRAYSIZE(wFSType));
|
GetWindowTextW(hFileSystem, wFSType, ARRAYSIZE(wFSType));
|
||||||
GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel));
|
GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel));
|
||||||
// TODO set sector size
|
// TODO set sector size
|
||||||
pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel,
|
pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel,
|
||||||
IsChecked(IDC_QUICKFORMAT), 4096, FormatExCallback);
|
IsChecked(IDC_QUICKFORMAT), 4096, FormatExCallback);
|
||||||
if (FormatErr == 0) {
|
if (!IS_ERROR(FormatStatus)) {
|
||||||
uprintf("Format completed.\n");
|
uprintf("Format completed.\n");
|
||||||
r = TRUE;
|
r = TRUE;
|
||||||
} else {
|
|
||||||
uprintf("Format error: 0x%02x\n", FormatErr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -623,14 +617,14 @@ static void __cdecl FormatThread(void* param)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!GetDriveHandle(num, &hDrive, NULL, TRUE)) {
|
if (!GetDriveHandle(num, &hDrive, NULL, TRUE)) {
|
||||||
// TODO: use FormatErr to report an error
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CreatePartition(hDrive);
|
r = CreatePartition(hDrive);
|
||||||
safe_closehandle(hDrive);
|
safe_closehandle(hDrive);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
// TODO: use FormatErr to report an error
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,12 +637,14 @@ static void __cdecl FormatThread(void* param)
|
||||||
}
|
}
|
||||||
if (i >= 10) {
|
if (i >= 10) {
|
||||||
uprintf("Unable to reopen drive post partitioning\n");
|
uprintf("Unable to reopen drive post partitioning\n");
|
||||||
// TODO: use FormatErr to report an error
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
safe_closehandle(hDrive);
|
safe_closehandle(hDrive);
|
||||||
|
|
||||||
if (!FormatDrive(drive_name[0])) {
|
if (!FormatDrive(drive_name[0])) {
|
||||||
|
// Error will be set by FormatDrive() in FormatStatus
|
||||||
|
uprintf("Format error: 0x%08X\n", FormatStatus);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,13 +851,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
case IDOK: // close application
|
case IDOK: // close application
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
if (format_thid != -1L) {
|
if (format_thid != -1L) {
|
||||||
// TODO: destroy MessageBox if operation completed while waiting
|
|
||||||
if (MessageBoxA(hMainDialog, "Cancelling may leave the device in an UNUSABLE state.\r\n"
|
if (MessageBoxA(hMainDialog, "Cancelling may leave the device in an UNUSABLE state.\r\n"
|
||||||
"If you are sure you want to cancel, click YES. Otherwise, click NO.",
|
"If you are sure you want to cancel, click YES. Otherwise, click NO.",
|
||||||
"Do you want to cancel?", MB_YESNO|MB_ICONWARNING) == IDYES) {
|
RUFUS_CANCELBOX_TITLE, MB_YESNO|MB_ICONWARNING) == IDYES) {
|
||||||
// Operation may have completed
|
// Operation may have completed in the meantime
|
||||||
if (format_thid != -1L) {
|
if (format_thid != -1L) {
|
||||||
FormatErr = -1;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
|
||||||
StatusPrintf("Cancelling - please wait...");
|
StatusPrintf("Cancelling - please wait...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -886,7 +881,6 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDC_START:
|
case IDC_START:
|
||||||
// TODO: disable all controls and replace Close with Cancel
|
|
||||||
if (format_thid != -1L) {
|
if (format_thid != -1L) {
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
}
|
}
|
||||||
|
@ -904,10 +898,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
SendMessage(hProgress, PBM_SETMARQUEE, TRUE, 0);
|
SendMessage(hProgress, PBM_SETMARQUEE, TRUE, 0);
|
||||||
}
|
}
|
||||||
DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex);
|
DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex);
|
||||||
|
FormatStatus = 0;
|
||||||
format_thid = _beginthread(FormatThread, 0, (void*)(uintptr_t)DeviceNum);
|
format_thid = _beginthread(FormatThread, 0, (void*)(uintptr_t)DeviceNum);
|
||||||
if (format_thid == -1L) {
|
if (format_thid == -1L) {
|
||||||
// TODO: handle error
|
|
||||||
uprintf("Unable to start formatting thread");
|
uprintf("Unable to start formatting thread");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANT_START_THREAD;
|
||||||
|
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -930,6 +926,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
|
|
||||||
case UM_FORMAT_COMPLETED:
|
case UM_FORMAT_COMPLETED:
|
||||||
format_thid = -1L;
|
format_thid = -1L;
|
||||||
|
// Close the cancel MessageBox if active
|
||||||
|
SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), RUFUS_CANCELBOX_TITLE), WM_COMMAND, IDNO, 0);
|
||||||
if (IsChecked(IDC_QUICKFORMAT)) {
|
if (IsChecked(IDC_QUICKFORMAT)) {
|
||||||
SendMessage(hProgress, PBM_SETMARQUEE, FALSE, 0);
|
SendMessage(hProgress, PBM_SETMARQUEE, FALSE, 0);
|
||||||
SetWindowLongPtr(hProgress, GWL_STYLE, ProgressStyle);
|
SetWindowLongPtr(hProgress, GWL_STYLE, ProgressStyle);
|
||||||
|
@ -938,9 +936,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
SendMessage(hProgress, PBM_SETPOS, 101, 0);
|
SendMessage(hProgress, PBM_SETPOS, 101, 0);
|
||||||
SendMessage(hProgress, PBM_SETRANGE, 0, 100<<16);
|
SendMessage(hProgress, PBM_SETRANGE, 0, 100<<16);
|
||||||
}
|
}
|
||||||
SendMessage(hProgress, PBM_SETPOS, FormatErr?0:100, 0);
|
SendMessage(hProgress, PBM_SETPOS, FormatStatus?0:100, 0);
|
||||||
// TODO: report cancelled status
|
StatusPrintf(!IS_ERROR(FormatStatus)?"DONE":
|
||||||
StatusPrintf(FormatErr?"FAILED":"DONE");
|
((SCODE_CODE(FormatStatus)==ERROR_CANCELLED)?"Cancelled":"FAILED"));
|
||||||
EnableControls(TRUE);
|
EnableControls(TRUE);
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
}
|
}
|
||||||
|
|
11
rufus.h
11
rufus.h
|
@ -15,7 +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
|
#include <winioctl.h> // for MEDIA_TYPE
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#define APP_VERSION "Rufus v1.0.0.1"
|
#define APP_VERSION "Rufus v1.0.0.1"
|
||||||
#define STR_NO_LABEL "NO_LABEL"
|
#define STR_NO_LABEL "NO_LABEL"
|
||||||
|
#define RUFUS_CANCELBOX_TITLE "Rufus - Cancellation"
|
||||||
#define DRIVE_INDEX_MIN 0x80
|
#define DRIVE_INDEX_MIN 0x80
|
||||||
#define DRIVE_INDEX_MAX 0xC0
|
#define DRIVE_INDEX_MAX 0xC0
|
||||||
#define MAX_DRIVES 16
|
#define MAX_DRIVES 16
|
||||||
|
@ -213,3 +214,11 @@ typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)(
|
||||||
WCHAR* DriveRoot,
|
WCHAR* DriveRoot,
|
||||||
ULONG CompressionFlags // FILE_SYSTEM_PROP_FLAG
|
ULONG CompressionFlags // FILE_SYSTEM_PROP_FLAG
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Custom application errors */
|
||||||
|
#define FAC(f) (f<<16)
|
||||||
|
#define ERROR_INCOMPATIBLE_FS (APPLICATION_ERROR_MASK|0x1201)
|
||||||
|
#define ERROR_CANT_QUICK_FORMAT (APPLICATION_ERROR_MASK|0x1202)
|
||||||
|
#define ERROR_INVALID_CLUSTER_SIZE (APPLICATION_ERROR_MASK|0x1203)
|
||||||
|
#define ERROR_INVALID_VOLUME_SIZE (APPLICATION_ERROR_MASK|0x1204)
|
||||||
|
#define ERROR_CANT_START_THREAD (APPLICATION_ERROR_MASK|0x1205)
|
||||||
|
|
Loading…
Reference in a new issue