mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-19 17:35:10 -04:00
[iso] cancellation improvements
* remove threaded cancellation, detect blocking and warn instead * also add hidden shortcut to disable ISO size check
This commit is contained in:
parent
d1f41309a9
commit
5d58b83ed8
5 changed files with 103 additions and 60 deletions
|
@ -560,10 +560,10 @@ DWORD WINAPI FormatThread(LPVOID param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: the only way to properly recover from a cancel will be through a device reset
|
|
||||||
// We issue a complete remount of the filesystem at the end on account of:
|
// We issue a complete remount of the filesystem at the end on account of:
|
||||||
// - Ensuring the file explorer properly detects that the volume was updated
|
// - Ensuring the file explorer properly detects that the volume was updated
|
||||||
// - Ensuring that an NTFS system will be reparsed so that it becomes bootable
|
// - Ensuring that an NTFS system will be reparsed so that it becomes bootable
|
||||||
|
// TODO: on cancellation, this can leave the drive unmounted!
|
||||||
if (GetVolumeNameForVolumeMountPointA(drive_name, drive_guid, sizeof(drive_guid))) {
|
if (GetVolumeNameForVolumeMountPointA(drive_name, drive_guid, sizeof(drive_guid))) {
|
||||||
if (DeleteVolumeMountPointA(drive_name)) {
|
if (DeleteVolumeMountPointA(drive_name)) {
|
||||||
Sleep(200);
|
Sleep(200);
|
||||||
|
|
56
src/iso.c
56
src/iso.c
|
@ -53,7 +53,6 @@
|
||||||
// How often should we update the progress bar (in 2K blocks) as updating
|
// How often should we update the progress bar (in 2K blocks) as updating
|
||||||
// the progress bar for every block will bring extraction to a crawl
|
// the progress bar for every block will bring extraction to a crawl
|
||||||
#define PROGRESS_THRESHOLD 1024
|
#define PROGRESS_THRESHOLD 1024
|
||||||
#define THREADED_CLOSE_THRESHOLD (20 * 1024 * 1024) // 20 MB
|
|
||||||
#define FOUR_GIGABYTES 4294967296LL
|
#define FOUR_GIGABYTES 4294967296LL
|
||||||
|
|
||||||
// Needed for UDF ISO access
|
// Needed for UDF ISO access
|
||||||
|
@ -61,7 +60,10 @@ CdIo_t* cdio_open (const char *psz_source, driver_id_t driver_id) {return NULL;}
|
||||||
void cdio_destroy (CdIo_t *p_cdio) {}
|
void cdio_destroy (CdIo_t *p_cdio) {}
|
||||||
|
|
||||||
RUFUS_ISO_REPORT iso_report;
|
RUFUS_ISO_REPORT iso_report;
|
||||||
|
int64_t iso_blocking_status = -1;
|
||||||
|
#define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0)
|
||||||
static const char *psz_extract_dir;
|
static const char *psz_extract_dir;
|
||||||
|
static const char *isolinux_name = "isolinux", *bootmgr_name = "bootmgr";
|
||||||
static uint64_t total_blocks, nb_blocks;
|
static uint64_t total_blocks, nb_blocks;
|
||||||
static BOOL scan_only = FALSE;
|
static BOOL scan_only = FALSE;
|
||||||
|
|
||||||
|
@ -89,26 +91,12 @@ DWORD WINAPI ISOCloseHandleThread(LPVOID param)
|
||||||
ExitThread(0);
|
ExitThread(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SAFE_CLOSEHANDLE_THREADED(handle) \
|
|
||||||
if (!threaded_close) { \
|
|
||||||
safe_closehandle(handle); \
|
|
||||||
} else { \
|
|
||||||
thid = CreateThread(NULL, 0, ISOCloseHandleThread, (LPVOID)handle, 0, NULL); \
|
|
||||||
while (WaitForSingleObject(thid, 1000) == WAIT_TIMEOUT) { \
|
|
||||||
if (!FormatStatus) continue; \
|
|
||||||
safe_closehandle(thid); \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
handle = NULL; \
|
|
||||||
threaded_close = FALSE; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns 0 on success, nonzero on error
|
// Returns 0 on success, nonzero on error
|
||||||
static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path)
|
static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path)
|
||||||
{
|
{
|
||||||
HANDLE thid, file_handle = NULL;
|
HANDLE file_handle = NULL;
|
||||||
DWORD buf_size, wr_size;
|
DWORD buf_size, wr_size;
|
||||||
BOOL threaded_close = FALSE;
|
BOOL r;
|
||||||
int i_length;
|
int i_length;
|
||||||
size_t i, nul_pos;
|
size_t i, nul_pos;
|
||||||
char* psz_fullpath;
|
char* psz_fullpath;
|
||||||
|
@ -138,7 +126,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
_mkdir(psz_fullpath);
|
_mkdir(psz_fullpath);
|
||||||
} else {
|
} else {
|
||||||
// Check for an "isolinux\" dir in root (psz_path = "")
|
// Check for an "isolinux\" dir in root (psz_path = "")
|
||||||
if ((*psz_path == 0) && (safe_strcmp(psz_basename, "isolinux") == 0))
|
if ((*psz_path == 0) && (safe_strcmp(psz_basename, isolinux_name) == 0))
|
||||||
iso_report.has_isolinux = TRUE;
|
iso_report.has_isolinux = TRUE;
|
||||||
}
|
}
|
||||||
p_udf_dirent2 = udf_opendir(p_udf_dirent);
|
p_udf_dirent2 = udf_opendir(p_udf_dirent);
|
||||||
|
@ -150,7 +138,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
i_file_length = udf_get_file_length(p_udf_dirent);
|
i_file_length = udf_get_file_length(p_udf_dirent);
|
||||||
if (scan_only) {
|
if (scan_only) {
|
||||||
// Check for a "bootmgr" file in root (psz_path = "")
|
// Check for a "bootmgr" file in root (psz_path = "")
|
||||||
if ((*psz_path == 0) && (safe_strcmp(psz_basename, "bootmgr") == 0))
|
if ((*psz_path == 0) && (safe_strcmp(psz_basename, bootmgr_name) == 0))
|
||||||
iso_report.has_bootmgr = TRUE;
|
iso_report.has_bootmgr = TRUE;
|
||||||
if (i_file_length >= FOUR_GIGABYTES)
|
if (i_file_length >= FOUR_GIGABYTES)
|
||||||
iso_report.has_4GB_file = TRUE;
|
iso_report.has_4GB_file = TRUE;
|
||||||
|
@ -177,8 +165,6 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
uprintf(" Unable to create file: %s\n", WindowsErrorString());
|
uprintf(" Unable to create file: %s\n", WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
threaded_close = (i_file_length > THREADED_CLOSE_THRESHOLD);
|
|
||||||
if (threaded_close) uprintf("will use threaded close\n");
|
|
||||||
while (i_file_length > 0) {
|
while (i_file_length > 0) {
|
||||||
if (FormatStatus) goto out;
|
if (FormatStatus) goto out;
|
||||||
memset(buf, 0, UDF_BLOCKSIZE);
|
memset(buf, 0, UDF_BLOCKSIZE);
|
||||||
|
@ -188,7 +174,8 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
buf_size = (DWORD)MIN(i_file_length, i_read);
|
buf_size = (DWORD)MIN(i_file_length, i_read);
|
||||||
if (!WriteFile(file_handle, buf, buf_size, &wr_size, NULL) || (buf_size != wr_size)) {
|
ISO_BLOCKING(r = WriteFile(file_handle, buf, buf_size, &wr_size, NULL));
|
||||||
|
if ((!r) || (buf_size != wr_size)) {
|
||||||
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -201,9 +188,8 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
// excellent job at compensating for our small blocks read/writes to max out the
|
// excellent job at compensating for our small blocks read/writes to max out the
|
||||||
// device's bandwidth.
|
// device's bandwidth.
|
||||||
// The drawback however is with cancellation. With a large file, CloseHandle()
|
// The drawback however is with cancellation. With a large file, CloseHandle()
|
||||||
// may take forever to complete on a large file and is not an interruptible
|
// may take forever to complete and is not interruptible. We try to detect this.
|
||||||
// operation. To compensate for this, we create a thread when needed.
|
ISO_BLOCKING(safe_closehandle(file_handle));
|
||||||
SAFE_CLOSEHANDLE_THREADED(file_handle);
|
|
||||||
}
|
}
|
||||||
safe_free(psz_fullpath);
|
safe_free(psz_fullpath);
|
||||||
}
|
}
|
||||||
|
@ -212,7 +198,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
out:
|
out:
|
||||||
if (p_udf_dirent != NULL)
|
if (p_udf_dirent != NULL)
|
||||||
udf_dirent_free(p_udf_dirent);
|
udf_dirent_free(p_udf_dirent);
|
||||||
SAFE_CLOSEHANDLE_THREADED(file_handle);
|
ISO_BLOCKING(safe_closehandle(file_handle));
|
||||||
safe_free(psz_fullpath);
|
safe_free(psz_fullpath);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -220,9 +206,9 @@ out:
|
||||||
// Returns 0 on success, nonzero on error
|
// Returns 0 on success, nonzero on error
|
||||||
static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
{
|
{
|
||||||
HANDLE thid, file_handle = NULL;
|
HANDLE file_handle = NULL;
|
||||||
DWORD buf_size, wr_size;
|
DWORD buf_size, wr_size;
|
||||||
BOOL threaded_close = FALSE;
|
BOOL s;
|
||||||
int i_length, r = 1;
|
int i_length, r = 1;
|
||||||
char psz_fullpath[1024], *psz_basename;
|
char psz_fullpath[1024], *psz_basename;
|
||||||
const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)];
|
const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)];
|
||||||
|
@ -259,7 +245,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
_mkdir(psz_fullpath);
|
_mkdir(psz_fullpath);
|
||||||
} else {
|
} else {
|
||||||
// Check for an "isolinux\" dir in root (psz_path = "")
|
// Check for an "isolinux\" dir in root (psz_path = "")
|
||||||
if ((*psz_path == 0) && (safe_strcmp(psz_basename, "isolinux") == 0))
|
if ((*psz_path == 0) && (safe_strcmp(psz_basename, isolinux_name) == 0))
|
||||||
iso_report.has_isolinux = TRUE;
|
iso_report.has_isolinux = TRUE;
|
||||||
}
|
}
|
||||||
if (iso_extract_files(p_iso, psz_iso_name))
|
if (iso_extract_files(p_iso, psz_iso_name))
|
||||||
|
@ -268,7 +254,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
i_file_length = p_statbuf->size;
|
i_file_length = p_statbuf->size;
|
||||||
if (scan_only) {
|
if (scan_only) {
|
||||||
// Check for a "bootmgr" file in root (psz_path = "")
|
// Check for a "bootmgr" file in root (psz_path = "")
|
||||||
if ((*psz_path == 0) && (safe_strcmp(psz_basename, "bootmgr") == 0))
|
if ((*psz_path == 0) && (safe_strcmp(psz_basename, bootmgr_name) == 0))
|
||||||
iso_report.has_bootmgr = TRUE;
|
iso_report.has_bootmgr = TRUE;
|
||||||
if (i_file_length >= FOUR_GIGABYTES)
|
if (i_file_length >= FOUR_GIGABYTES)
|
||||||
iso_report.has_4GB_file = TRUE;
|
iso_report.has_4GB_file = TRUE;
|
||||||
|
@ -293,7 +279,6 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
uprintf(" Unable to create file: %s\n", WindowsErrorString());
|
uprintf(" Unable to create file: %s\n", WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
threaded_close = (i_file_length > THREADED_CLOSE_THRESHOLD);
|
|
||||||
for (i = 0; i_file_length > 0; i++) {
|
for (i = 0; i_file_length > 0; i++) {
|
||||||
if (FormatStatus) goto out;
|
if (FormatStatus) goto out;
|
||||||
memset(buf, 0, ISO_BLOCKSIZE);
|
memset(buf, 0, ISO_BLOCKSIZE);
|
||||||
|
@ -304,7 +289,8 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE);
|
buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE);
|
||||||
if (!WriteFile(file_handle, buf, buf_size, &wr_size, NULL) || (buf_size != wr_size)) {
|
ISO_BLOCKING(s = WriteFile(file_handle, buf, buf_size, &wr_size, NULL));
|
||||||
|
if ((!s) || (buf_size != wr_size)) {
|
||||||
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -313,13 +299,13 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0);
|
SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SAFE_CLOSEHANDLE_THREADED(file_handle);
|
ISO_BLOCKING(safe_closehandle(file_handle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r = 0;
|
r = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
SAFE_CLOSEHANDLE_THREADED(file_handle);
|
ISO_BLOCKING(safe_closehandle(file_handle));
|
||||||
_cdio_list_free(p_entlist, true);
|
_cdio_list_free(p_entlist, true);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -360,6 +346,7 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, bool scan)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
nb_blocks = 0;
|
nb_blocks = 0;
|
||||||
|
iso_blocking_status = 0;
|
||||||
SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
|
SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
|
||||||
SendMessage(hISOProgressBar, PBM_SETPOS, 0, 0);
|
SendMessage(hISOProgressBar, PBM_SETPOS, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -390,6 +377,7 @@ try_iso:
|
||||||
r = iso_extract_files(p_iso, "");
|
r = iso_extract_files(p_iso, "");
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
iso_blocking_status = -1;
|
||||||
if (scan_only) {
|
if (scan_only) {
|
||||||
// We use the fact that UDF_BLOCKSIZE and ISO_BLOCKSIZE are the same here
|
// We use the fact that UDF_BLOCKSIZE and ISO_BLOCKSIZE are the same here
|
||||||
iso_report.projected_size = total_blocks * ISO_BLOCKSIZE;
|
iso_report.projected_size = total_blocks * ISO_BLOCKSIZE;
|
||||||
|
|
85
src/rufus.c
85
src/rufus.c
|
@ -44,8 +44,8 @@ static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "exFAT" }
|
||||||
static 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",
|
"16 kilobytes", "32 kilobytes", "64 kilobytes", "128 kilobytes", "256 kilobytes", "512 kilobytes",
|
||||||
"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" };
|
"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" };
|
||||||
// For LGP set/restore
|
static BOOL existing_key = FALSE; // For LGP set/restore
|
||||||
static BOOL existing_key = FALSE;
|
static BOOL iso_size_check = TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals
|
* Globals
|
||||||
|
@ -67,6 +67,7 @@ static HICON hIconDisc;
|
||||||
static StrArray DriveID, DriveLabel;
|
static StrArray DriveID, DriveLabel;
|
||||||
static char szTimer[12] = "00:00:00";
|
static char szTimer[12] = "00:00:00";
|
||||||
static unsigned int timer;
|
static unsigned int timer;
|
||||||
|
static int64_t last_iso_blocking_status;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following is used to allocate slots within the progress bar
|
* The following is used to allocate slots within the progress bar
|
||||||
|
@ -472,7 +473,6 @@ BOOL CreatePartition(HANDLE hDrive)
|
||||||
break;
|
break;
|
||||||
case FS_NTFS:
|
case FS_NTFS:
|
||||||
case FS_EXFAT:
|
case FS_EXFAT:
|
||||||
// TODO: but how do we set this thing up afterwards?
|
|
||||||
DriveLayoutEx->PartitionEntry[0].Mbr.PartitionType = 0x07; // NTFS
|
DriveLayoutEx->PartitionEntry[0].Mbr.PartitionType = 0x07; // NTFS
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -626,7 +626,6 @@ static void InitProgress(void)
|
||||||
}
|
}
|
||||||
if (IsChecked(IDC_DOS)) {
|
if (IsChecked(IDC_DOS)) {
|
||||||
// 1 extra slot for PBR writing
|
// 1 extra slot for PBR writing
|
||||||
// TODO: ISO
|
|
||||||
switch (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType))) {
|
switch (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType))) {
|
||||||
case DT_WINME:
|
case DT_WINME:
|
||||||
nb_slots[OP_DOS] = 3+1;
|
nb_slots[OP_DOS] = 3+1;
|
||||||
|
@ -887,6 +886,35 @@ static void CALLBACK ClockTimer(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dw
|
||||||
SendMessageA(GetDlgItem(hWnd, IDC_STATUS), SB_SETTEXTA, SBT_OWNERDRAW | 1, (LPARAM)szTimer);
|
SendMessageA(GetDlgItem(hWnd, IDC_STATUS), SB_SETTEXTA, SBT_OWNERDRAW | 1, (LPARAM)szTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detect and notify about a blocking operation during ISO extraction cancellation
|
||||||
|
*/
|
||||||
|
static void CALLBACK BlockingTimer(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||||||
|
{
|
||||||
|
static BOOL user_notified = FALSE;
|
||||||
|
if (iso_blocking_status < 0) {
|
||||||
|
KillTimer(hMainDialog, TID_BLOCKING_TIMER);
|
||||||
|
user_notified = FALSE;
|
||||||
|
uprintf("Killed blocking I/O timer\n");
|
||||||
|
} else if(!user_notified) {
|
||||||
|
if (last_iso_blocking_status == iso_blocking_status) {
|
||||||
|
// A write or close operation hasn't made any progress since our last check
|
||||||
|
user_notified = TRUE;
|
||||||
|
uprintf("Blocking I/O operation detected\n");
|
||||||
|
MessageBoxU(hMainDialog,
|
||||||
|
"Rufus detected that Windows is still flushing its internal buffers\n"
|
||||||
|
"onto the USB device.\n\n"
|
||||||
|
"Depending on the speed of your USB device, this operation may\n"
|
||||||
|
"take a long time to complete, especially for large files.\n\n"
|
||||||
|
"We recommend that you let Windows finish, to avoid corruption.\n"
|
||||||
|
"But if you grow tired of waiting, you can just unplug the device...",
|
||||||
|
RUFUS_BLOCKING_IO_TITLE, MB_OK|MB_ICONINFORMATION);
|
||||||
|
} else {
|
||||||
|
last_iso_blocking_status = iso_blocking_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for the modeless ISO extraction progress */
|
/* Callback for the modeless ISO extraction progress */
|
||||||
BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
@ -906,10 +934,15 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
switch (LOWORD(wParam)) {
|
switch (LOWORD(wParam)) {
|
||||||
case IDC_ISO_ABORT:
|
case IDC_ISO_ABORT:
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
|
||||||
// if (format_thid != NULL)
|
PrintStatus(0, FALSE, "Cancelling - Please wait...");
|
||||||
// CancelSynchronousIo(format_thid);
|
uprintf("Cancelling (from ISO proc.)\n");
|
||||||
PrintStatus(0, FALSE, "Cancelling - This might take a while...");
|
EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), FALSE);
|
||||||
uprintf("Cancelling (ISO)\n");
|
EnableWindow(GetDlgItem(hMainDialog, IDCANCEL), FALSE);
|
||||||
|
// Start a timer to detect blocking operations during ISO file extraction
|
||||||
|
if (iso_blocking_status >= 0) {
|
||||||
|
last_iso_blocking_status = iso_blocking_status;
|
||||||
|
SetTimer(hMainDialog, TID_BLOCKING_TIMER, 5000, BlockingTimer);
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
case WM_CLOSE: // prevent closure using Alt-F4
|
case WM_CLOSE: // prevent closure using Alt-F4
|
||||||
|
@ -921,7 +954,10 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
// The scanning process can be blocking for message processing => use a thread
|
// The scanning process can be blocking for message processing => use a thread
|
||||||
DWORD WINAPI ISOScanThread(LPVOID param)
|
DWORD WINAPI ISOScanThread(LPVOID param)
|
||||||
{
|
{
|
||||||
size_t i;
|
int i;
|
||||||
|
|
||||||
|
if (iso_path == NULL)
|
||||||
|
goto out;
|
||||||
PrintStatus(0, TRUE, "Scanning ISO image...\n");
|
PrintStatus(0, TRUE, "Scanning ISO image...\n");
|
||||||
if (!ExtractISO(iso_path, "", TRUE)) {
|
if (!ExtractISO(iso_path, "", TRUE)) {
|
||||||
PrintStatus(0, TRUE, "Failed to scan ISO image.");
|
PrintStatus(0, TRUE, "Failed to scan ISO image.");
|
||||||
|
@ -934,7 +970,7 @@ DWORD WINAPI ISOScanThread(LPVOID param)
|
||||||
"ISO images that rely on 'bootmgr' - sorry.", "Unsupported ISO", MB_OK|MB_ICONINFORMATION);
|
"ISO images that rely on 'bootmgr' - sorry.", "Unsupported ISO", MB_OK|MB_ICONINFORMATION);
|
||||||
safe_free(iso_path);
|
safe_free(iso_path);
|
||||||
} else {
|
} else {
|
||||||
for (i=safe_strlen(iso_path); (i>=0)&&(iso_path[i] != '\\'); i--);
|
for (i=(int)safe_strlen(iso_path); (i>0)&&(iso_path[i]!='\\'); i--);
|
||||||
PrintStatus(0, TRUE, "Using ISO: '%s'\n", &iso_path[i+1]);
|
PrintStatus(0, TRUE, "Using ISO: '%s'\n", &iso_path[i+1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,18 +1131,27 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
switch(LOWORD(wParam)) {
|
switch(LOWORD(wParam)) {
|
||||||
case IDOK: // close application
|
case IDOK: // close application
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
|
EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), FALSE);
|
||||||
|
EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
|
||||||
if (format_thid != NULL) {
|
if (format_thid != NULL) {
|
||||||
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.",
|
||||||
RUFUS_CANCELBOX_TITLE, MB_YESNO|MB_ICONWARNING) == IDYES) {
|
RUFUS_CANCELBOX_TITLE, MB_YESNO|MB_ICONWARNING) == IDYES) {
|
||||||
// Operation may have completed in the meantime
|
// Operation may have completed in the meantime
|
||||||
if (format_thid != NULL) {
|
if (format_thid != NULL) {
|
||||||
// CancelSynchronousIo(format_thid);
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
|
||||||
PrintStatus(0, FALSE, "Cancelling - Please wait...");
|
PrintStatus(0, FALSE, "Cancelling - Please wait...");
|
||||||
uprintf("Cancelling (General)\n");
|
uprintf("Cancelling (from main app)\n");
|
||||||
|
// Start a timer to detect blocking operations during ISO file extraction
|
||||||
|
if (iso_blocking_status >= 0) {
|
||||||
|
last_iso_blocking_status = iso_blocking_status;
|
||||||
|
SetTimer(hMainDialog, TID_BLOCKING_TIMER, 3000, BlockingTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), TRUE);
|
||||||
|
EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
|
||||||
|
}
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
}
|
}
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
|
@ -1215,7 +1260,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
"No ISO image selected...", MB_OK|MB_ICONERROR);
|
"No ISO image selected...", MB_OK|MB_ICONERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (iso_report.projected_size > (uint64_t)SelectedDrive.DiskSize) {
|
if ((iso_size_check) && (iso_report.projected_size > (uint64_t)SelectedDrive.DiskSize)) {
|
||||||
MessageBoxA(hMainDialog, "This ISO image is too big "
|
MessageBoxA(hMainDialog, "This ISO image is too big "
|
||||||
"for the selected target.", "ISO image too big...", MB_OK|MB_ICONERROR);
|
"for the selected target.", "ISO image too big...", MB_OK|MB_ICONERROR);
|
||||||
break;
|
break;
|
||||||
|
@ -1266,16 +1311,18 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
format_thid = NULL;
|
format_thid = NULL;
|
||||||
// Stop the timer
|
// Stop the timer
|
||||||
KillTimer(hMainDialog, TID_APP_TIMER);
|
KillTimer(hMainDialog, TID_APP_TIMER);
|
||||||
// Close the cancel MessageBox if active
|
// Close the cancel MessageBox and Blocking notification if active
|
||||||
SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), RUFUS_CANCELBOX_TITLE), WM_COMMAND, IDNO, 0);
|
SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), RUFUS_CANCELBOX_TITLE), WM_COMMAND, IDNO, 0);
|
||||||
|
SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), RUFUS_BLOCKING_IO_TITLE), WM_COMMAND, IDYES, 0);
|
||||||
|
EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), TRUE);
|
||||||
|
EnableWindow(GetDlgItem(hMainDialog, IDCANCEL), TRUE);
|
||||||
EnableControls(TRUE);
|
EnableControls(TRUE);
|
||||||
GetUSBDevices();
|
GetUSBDevices();
|
||||||
if (!IS_ERROR(FormatStatus)) {
|
if (!IS_ERROR(FormatStatus)) {
|
||||||
PrintStatus(0, FALSE, "DONE");
|
PrintStatus(0, FALSE, "DONE");
|
||||||
} else if (SCODE_CODE(FormatStatus) == ERROR_CANCELLED) {
|
} else if (SCODE_CODE(FormatStatus) == ERROR_CANCELLED) {
|
||||||
PrintStatus(0, FALSE, "Cancelled");
|
PrintStatus(0, FALSE, "Cancelled");
|
||||||
Notification(MSG_INFO, "Cancelled", "Operation cancelled by the user.\n"
|
Notification(MSG_INFO, "Cancelled", "Operation cancelled by the user.");
|
||||||
"If you aborted during file extraction, you should replug the drive...");
|
|
||||||
} else {
|
} else {
|
||||||
PrintStatus(0, FALSE, "FAILED");
|
PrintStatus(0, FALSE, "FAILED");
|
||||||
Notification(MSG_ERROR, "Error", "Error: %s", StrError(FormatStatus));
|
Notification(MSG_ERROR, "Error", "Error: %s", StrError(FormatStatus));
|
||||||
|
@ -1347,6 +1394,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
while(GetMessage(&msg, NULL, 0, 0)) {
|
while(GetMessage(&msg, NULL, 0, 0)) {
|
||||||
// The following ensures the processing of the ISO progress window messages
|
// The following ensures the processing of the ISO progress window messages
|
||||||
if (!IsWindow(hISOProgressDlg) || !IsDialogMessage(hISOProgressDlg, &msg)) {
|
if (!IsWindow(hISOProgressDlg) || !IsDialogMessage(hISOProgressDlg, &msg)) {
|
||||||
|
// Alt-S => Disable size limit
|
||||||
|
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'S')) {
|
||||||
|
iso_size_check = !iso_size_check;
|
||||||
|
PrintStatus(0, FALSE, "ISO size check %s", iso_size_check?"enabled":"disabled");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#ifdef DISABLE_AUTORUN
|
#ifdef DISABLE_AUTORUN
|
||||||
// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
|
// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
|
||||||
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) {
|
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) {
|
||||||
|
|
|
@ -22,14 +22,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/* Program options */
|
/* Program options */
|
||||||
#define RUFUS_DEBUG // print debug info to Debug facility (use debugview to consult)
|
#define RUFUS_DEBUG // print debug info to Debug facility
|
||||||
#define DISABLE_AUTORUN // disable new USB drive notification from explorer when application is running
|
#define DISABLE_AUTORUN // disable new USB drive notification from explorer when application is running
|
||||||
|
|
||||||
/* Features not ready for prime time and that may *DESTROY* your data - USE AT YOUR OWN RISKS! */
|
/* Features not ready for prime time and that may *DESTROY* your data - USE AT YOUR OWN RISKS! */
|
||||||
//#define RUFUS_TEST
|
//#define RUFUS_TEST
|
||||||
|
|
||||||
#define STR_NO_LABEL "NO_LABEL"
|
#define STR_NO_LABEL "NO_LABEL"
|
||||||
#define RUFUS_CANCELBOX_TITLE "Rufus - Cancellation"
|
#define RUFUS_CANCELBOX_TITLE "Rufus - Cancellation"
|
||||||
|
#define RUFUS_BLOCKING_IO_TITLE "Rufus - Flushing buffers"
|
||||||
#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
|
||||||
|
@ -93,7 +93,8 @@ enum notification_type {
|
||||||
enum timer_type {
|
enum timer_type {
|
||||||
TID_MESSAGE = 0x1000,
|
TID_MESSAGE = 0x1000,
|
||||||
TID_BADBLOCKS_UPDATE,
|
TID_BADBLOCKS_UPDATE,
|
||||||
TID_APP_TIMER
|
TID_APP_TIMER,
|
||||||
|
TID_BLOCKING_TIMER
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Action type, for progress bar breakdown */
|
/* Action type, for progress bar breakdown */
|
||||||
|
@ -165,6 +166,7 @@ extern RUFUS_DRIVE_INFO SelectedDrive;
|
||||||
extern const int nb_steps[FS_MAX];
|
extern const int nb_steps[FS_MAX];
|
||||||
extern BOOL bWithFreeDOS;
|
extern BOOL bWithFreeDOS;
|
||||||
extern RUFUS_ISO_REPORT iso_report;
|
extern RUFUS_ISO_REPORT iso_report;
|
||||||
|
extern int64_t iso_blocking_status;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shared prototypes
|
* Shared prototypes
|
||||||
|
|
12
src/rufus.rc
12
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 206, 278
|
IDD_DIALOG DIALOGEX 12, 12, 206, 278
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_APPWINDOW
|
EXSTYLE WS_EX_APPWINDOW
|
||||||
CAPTION "Rufus v1.0.8.128"
|
CAPTION "Rufus v1.0.8.129"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
DEFPUSHBUTTON "Start",IDC_START,94,236,50,14
|
DEFPUSHBUTTON "Start",IDC_START,94,236,50,14
|
||||||
|
@ -71,7 +71,7 @@ BEGIN
|
||||||
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
|
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
|
||||||
CONTROL "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL,
|
CONTROL "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL,
|
||||||
"SysLink",WS_TABSTOP,46,47,114,9
|
"SysLink",WS_TABSTOP,46,47,114,9
|
||||||
LTEXT "Version 1.0.8 (Build 128)",IDC_STATIC,46,19,78,8
|
LTEXT "Version 1.0.8 (Build 129)",IDC_STATIC,46,19,78,8
|
||||||
PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP
|
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
|
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
|
LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8
|
||||||
|
@ -223,8 +223,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,0,8,128
|
FILEVERSION 1,0,8,129
|
||||||
PRODUCTVERSION 1,0,8,128
|
PRODUCTVERSION 1,0,8,129
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -241,13 +241,13 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "akeo.ie"
|
VALUE "CompanyName", "akeo.ie"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "1.0.8.128"
|
VALUE "FileVersion", "1.0.8.129"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
||||||
VALUE "OriginalFilename", "rufus.exe"
|
VALUE "OriginalFilename", "rufus.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "1.0.8.128"
|
VALUE "ProductVersion", "1.0.8.129"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue