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 hDeviceTooltip = NULL, hFSTooltip = NULL;
|
||||
static StrArray DriveID, DriveLabel;
|
||||
static DWORD FormatErr;
|
||||
static DWORD FormatStatus;
|
||||
|
||||
#ifdef RUFUS_DEBUG
|
||||
void _uprintf(const char *format, ...)
|
||||
|
@ -209,7 +209,7 @@ static BOOL GetDriveHandle(DWORD DriveIndex, HANDLE* hDrive, char* DriveLetter,
|
|||
safe_closehandle(*hDrive);
|
||||
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;
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ static BOOL GetDriveHandle(DWORD DriveIndex, HANDLE* hDrive, char* DriveLetter,
|
|||
}
|
||||
|
||||
if (DriveLetter != NULL) {
|
||||
*DriveLetter = *drive?*drive:' '; // TODO: handle NUL char upstream
|
||||
*DriveLetter = *drive?*drive:' ';
|
||||
}
|
||||
|
||||
return (*hDrive != INVALID_HANDLE_VALUE);
|
||||
|
@ -293,6 +293,7 @@ static BOOL GetDriveInfo(void)
|
|||
if (DriveLayout->PartitionEntry[i].Mbr.PartitionType != PARTITION_ENTRY_UNUSED) {
|
||||
uprintf("Partition #%d:\n", ++nb_partitions);
|
||||
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)",
|
||||
GetPartitionType(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;
|
||||
int task_number = 0;
|
||||
|
||||
if (FormatErr != 0) return FALSE;
|
||||
if (IS_ERROR(FormatStatus))
|
||||
return FALSE;
|
||||
|
||||
switch(Command) {
|
||||
case FCC_PROGRESS:
|
||||
|
@ -517,65 +519,60 @@ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command,
|
|||
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);
|
||||
uprintf("Format task %d/? completed.\n", ++task_number);
|
||||
break;
|
||||
case FCC_DONE:
|
||||
if(*(BOOLEAN*)Data == FALSE) {
|
||||
uprintf("Error while formatting.\n");
|
||||
FormatErr = FCC_DONE;
|
||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE;
|
||||
}
|
||||
break;
|
||||
case FCC_INCOMPATIBLE_FILE_SYSTEM:
|
||||
uprintf("Incompatible File System\n");
|
||||
FormatErr = Command;
|
||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INCOMPATIBLE_FS;
|
||||
break;
|
||||
case FCC_ACCESS_DENIED:
|
||||
uprintf("Access denied\n");
|
||||
FormatErr = Command;
|
||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case FCC_MEDIA_WRITE_PROTECTED:
|
||||
uprintf("Media is write protected\n");
|
||||
FormatErr = Command;
|
||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_PROTECT;
|
||||
break;
|
||||
case FCC_VOLUME_IN_USE:
|
||||
uprintf("Volume is in use\n");
|
||||
FormatErr = Command;
|
||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_DEVICE_IN_USE;
|
||||
break;
|
||||
case FCC_CANT_QUICK_FORMAT:
|
||||
uprintf("Cannot quick format this volume\n");
|
||||
FormatErr = Command;
|
||||
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_INVALID_LABEL;
|
||||
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;
|
||||
case FCC_CLUSTER_SIZE_TOO_SMALL:
|
||||
uprintf("Allocation unit size is too %s\n", FCC_CLUSTER_SIZE_TOO_BIG?"big":"small");
|
||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_CLUSTER_SIZE;
|
||||
break;
|
||||
case FCC_VOLUME_TOO_BIG:
|
||||
uprintf("Volume is too big\n");
|
||||
FormatErr = Command;
|
||||
break;
|
||||
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\n");
|
||||
FormatErr = Command;
|
||||
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 (FormatErr == 0);
|
||||
return (!IS_ERROR(FormatStatus));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -594,17 +591,14 @@ static BOOL FormatDrive(char DriveLetter)
|
|||
PF_INIT_OR_OUT(FormatEx, fmifs);
|
||||
|
||||
// TODO: properly set MediaType
|
||||
FormatErr = 0;
|
||||
GetWindowTextW(hFileSystem, wFSType, ARRAYSIZE(wFSType));
|
||||
GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel));
|
||||
// TODO set sector size
|
||||
pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel,
|
||||
IsChecked(IDC_QUICKFORMAT), 4096, FormatExCallback);
|
||||
if (FormatErr == 0) {
|
||||
if (!IS_ERROR(FormatStatus)) {
|
||||
uprintf("Format completed.\n");
|
||||
r = TRUE;
|
||||
} else {
|
||||
uprintf("Format error: 0x%02x\n", FormatErr);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -623,14 +617,14 @@ static void __cdecl FormatThread(void* param)
|
|||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
r = CreatePartition(hDrive);
|
||||
safe_closehandle(hDrive);
|
||||
if (!r) {
|
||||
// TODO: use FormatErr to report an error
|
||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -643,12 +637,14 @@ static void __cdecl FormatThread(void* param)
|
|||
}
|
||||
if (i >= 10) {
|
||||
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;
|
||||
}
|
||||
safe_closehandle(hDrive);
|
||||
|
||||
if (!FormatDrive(drive_name[0])) {
|
||||
// Error will be set by FormatDrive() in FormatStatus
|
||||
uprintf("Format error: 0x%08X\n", FormatStatus);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -855,13 +851,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
case IDOK: // close application
|
||||
case IDCANCEL:
|
||||
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 you are sure you want to cancel, click YES. Otherwise, click NO.",
|
||||
"Do you want to cancel?", MB_YESNO|MB_ICONWARNING) == IDYES) {
|
||||
// Operation may have completed
|
||||
RUFUS_CANCELBOX_TITLE, MB_YESNO|MB_ICONWARNING) == IDYES) {
|
||||
// Operation may have completed in the meantime
|
||||
if (format_thid != -1L) {
|
||||
FormatErr = -1;
|
||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
|
||||
StatusPrintf("Cancelling - please wait...");
|
||||
}
|
||||
}
|
||||
|
@ -886,7 +881,6 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
}
|
||||
break;
|
||||
case IDC_START:
|
||||
// TODO: disable all controls and replace Close with Cancel
|
||||
if (format_thid != -1L) {
|
||||
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);
|
||||
}
|
||||
DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex);
|
||||
FormatStatus = 0;
|
||||
format_thid = _beginthread(FormatThread, 0, (void*)(uintptr_t)DeviceNum);
|
||||
if (format_thid == -1L) {
|
||||
// TODO: handle error
|
||||
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:
|
||||
format_thid = -1L;
|
||||
// Close the cancel MessageBox if active
|
||||
SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), RUFUS_CANCELBOX_TITLE), WM_COMMAND, IDNO, 0);
|
||||
if (IsChecked(IDC_QUICKFORMAT)) {
|
||||
SendMessage(hProgress, PBM_SETMARQUEE, FALSE, 0);
|
||||
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_SETRANGE, 0, 100<<16);
|
||||
}
|
||||
SendMessage(hProgress, PBM_SETPOS, FormatErr?0:100, 0);
|
||||
// TODO: report cancelled status
|
||||
StatusPrintf(FormatErr?"FAILED":"DONE");
|
||||
SendMessage(hProgress, PBM_SETPOS, FormatStatus?0:100, 0);
|
||||
StatusPrintf(!IS_ERROR(FormatStatus)?"DONE":
|
||||
((SCODE_CODE(FormatStatus)==ERROR_CANCELLED)?"Cancelled":"FAILED"));
|
||||
EnableControls(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
|
||||
* 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
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
|||
|
||||
#define APP_VERSION "Rufus v1.0.0.1"
|
||||
#define STR_NO_LABEL "NO_LABEL"
|
||||
#define RUFUS_CANCELBOX_TITLE "Rufus - Cancellation"
|
||||
#define DRIVE_INDEX_MIN 0x80
|
||||
#define DRIVE_INDEX_MAX 0xC0
|
||||
#define MAX_DRIVES 16
|
||||
|
@ -213,3 +214,11 @@ typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)(
|
|||
WCHAR* DriveRoot,
|
||||
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