mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-19 09:25:12 -04:00
[iso] bootable NTFS from ISO image [EXPERIMENTAL]
* bootmgr ISOs only * extraction and ISO support UI improvements * UTF8 support through CreateFileU * cancellation on ISO file extraction * switch to using CreateThread
This commit is contained in:
parent
22276ccb5a
commit
472db8b592
7 changed files with 232 additions and 117 deletions
24
src/format.c
24
src/format.c
|
@ -371,7 +371,8 @@ static BOOL WritePBR(HANDLE hLogicalVolume, BOOL bFreeDOS)
|
||||||
uprintf("Confirmed new volume has an NTFS boot sector\n");
|
uprintf("Confirmed new volume has an NTFS boot sector\n");
|
||||||
if (!write_ntfs_br(&fake_fd)) break;
|
if (!write_ntfs_br(&fake_fd)) break;
|
||||||
// Note: NTFS requires a full remount after writing the PBR. We dismount when we lock
|
// Note: NTFS requires a full remount after writing the PBR. We dismount when we lock
|
||||||
// so that's not an issue, but if you don't remount, you don't boot!
|
// and also go through a forced remount, so that shouldn't be an issue.
|
||||||
|
// But with NTFS, if you don't remount, you don't boot!
|
||||||
return TRUE;
|
return TRUE;
|
||||||
default:
|
default:
|
||||||
uprintf("unsupported FS for FS BR processing\n");
|
uprintf("unsupported FS for FS BR processing\n");
|
||||||
|
@ -384,7 +385,7 @@ static BOOL WritePBR(HANDLE hLogicalVolume, BOOL bFreeDOS)
|
||||||
/*
|
/*
|
||||||
* Standalone thread for the formatting operation
|
* Standalone thread for the formatting operation
|
||||||
*/
|
*/
|
||||||
void __cdecl FormatThread(void* param)
|
DWORD WINAPI FormatThread(LPVOID param)
|
||||||
{
|
{
|
||||||
DWORD num = (DWORD)(uintptr_t)param;
|
DWORD num = (DWORD)(uintptr_t)param;
|
||||||
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
|
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
|
||||||
|
@ -397,11 +398,6 @@ void __cdecl FormatThread(void* param)
|
||||||
FILE* log_fd;
|
FILE* log_fd;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
#ifdef RUFUS_TEST
|
|
||||||
ExtractISO(ISO_IMAGE, ISO_DEST, FALSE);
|
|
||||||
goto out;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hPhysicalDrive = GetDriveHandle(num, NULL, TRUE, TRUE);
|
hPhysicalDrive = GetDriveHandle(num, NULL, TRUE, TRUE);
|
||||||
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
||||||
|
@ -542,21 +538,29 @@ void __cdecl FormatThread(void* param)
|
||||||
if (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) != DT_ISO) {
|
if (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) != DT_ISO) {
|
||||||
PrintStatus(0, TRUE, "Copying DOS files...");
|
PrintStatus(0, TRUE, "Copying DOS files...");
|
||||||
if (!ExtractDOS(drive_name)) {
|
if (!ExtractDOS(drive_name)) {
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
|
if (!FormatStatus)
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
} else if (iso_path != NULL) {
|
||||||
|
PrintStatus(0, TRUE, "Copying ISO files...");
|
||||||
|
drive_name[2] = 0;
|
||||||
|
if ( (!ExtractISO(iso_path, drive_name, FALSE)) && (!FormatStatus)) {
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
|
||||||
|
}
|
||||||
|
drive_name[2] = '\\';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Syslinux requires patching of the PBR after the files have been extracted
|
// Syslinux requires patching of the PBR after the files have been extracted
|
||||||
case DT_SYSLINUX:
|
case DT_SYSLINUX:
|
||||||
if (!InstallSyslinux(num, drive_name)) {
|
if (!InstallSyslinux(num, drive_name)) {
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
@ -579,5 +583,5 @@ out:
|
||||||
safe_unlockclose(hLogicalVolume);
|
safe_unlockclose(hLogicalVolume);
|
||||||
safe_unlockclose(hPhysicalDrive);
|
safe_unlockclose(hPhysicalDrive);
|
||||||
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
|
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
|
||||||
_endthread();
|
ExitThread(0);
|
||||||
}
|
}
|
||||||
|
|
164
src/iso.c
164
src/iso.c
|
@ -52,8 +52,9 @@
|
||||||
#endif
|
#endif
|
||||||
// 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_UPDATE 1024
|
#define PROGRESS_THRESHOLD 1024
|
||||||
#define FOUR_GIGABYTES 4294967296LL
|
#define THREADED_CLOSE_THRESHOLD (20 * 1024 * 1024) // 20 MB
|
||||||
|
#define FOUR_GIGABYTES 4294967296LL
|
||||||
|
|
||||||
// Needed for UDF ISO access
|
// Needed for UDF ISO access
|
||||||
CdIo_t* cdio_open (const char *psz_source, driver_id_t driver_id) {return NULL;}
|
CdIo_t* cdio_open (const char *psz_source, driver_id_t driver_id) {return NULL;}
|
||||||
|
@ -64,12 +65,52 @@ static const char *psz_extract_dir;
|
||||||
static uint64_t total_blocks, nb_blocks;
|
static uint64_t total_blocks, nb_blocks;
|
||||||
static BOOL scan_only = FALSE;
|
static BOOL scan_only = FALSE;
|
||||||
|
|
||||||
// TODO: Unicode support, timestamp & permissions preservation
|
// TODO: Timestamp & permissions preservation
|
||||||
|
|
||||||
|
// Convert a file size to human readable
|
||||||
|
static __inline char* size_to_hr(int64_t size)
|
||||||
|
{
|
||||||
|
int suffix = 0;
|
||||||
|
static char str_size[24];
|
||||||
|
const char* sizes[] = { "bytes", "KB", "MB", "GB", "TB", "PB" };
|
||||||
|
double hr_size = (double)size;
|
||||||
|
while ((suffix < ARRAYSIZE(sizes)) && (hr_size >= 1024.0)) {
|
||||||
|
hr_size /= 1024.0;
|
||||||
|
suffix++;
|
||||||
|
}
|
||||||
|
safe_sprintf(str_size, sizeof(str_size), " (%0.1f %s)", hr_size, sizes[suffix]);
|
||||||
|
return str_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interruptible thread for handle closure on large files
|
||||||
|
DWORD WINAPI ISOCloseHandleThread(LPVOID param)
|
||||||
|
{
|
||||||
|
CloseHandle((HANDLE)param);
|
||||||
|
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
|
||||||
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)
|
||||||
{
|
{
|
||||||
FILE *fd = NULL;
|
HANDLE thid, file_handle = NULL;
|
||||||
|
DWORD buf_size, wr_size;
|
||||||
|
BOOL threaded_close = FALSE;
|
||||||
int i_length;
|
int i_length;
|
||||||
|
size_t i, nul_pos;
|
||||||
char* psz_fullpath;
|
char* psz_fullpath;
|
||||||
const char* psz_basename;
|
const char* psz_basename;
|
||||||
udf_dirent_t *p_udf_dirent2;
|
udf_dirent_t *p_udf_dirent2;
|
||||||
|
@ -82,19 +123,24 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
while ((p_udf_dirent = udf_readdir(p_udf_dirent)) != NULL) {
|
while ((p_udf_dirent = udf_readdir(p_udf_dirent)) != NULL) {
|
||||||
if (FormatStatus) goto out;
|
if (FormatStatus) goto out;
|
||||||
psz_basename = udf_get_filename(p_udf_dirent);
|
psz_basename = udf_get_filename(p_udf_dirent);
|
||||||
i_length = (int)(3 + strlen(psz_path) + strlen(psz_basename) + strlen(psz_extract_dir));
|
i_length = (int)(3 + strlen(psz_path) + strlen(psz_basename) + strlen(psz_extract_dir) + 24);
|
||||||
psz_fullpath = (char*)calloc(sizeof(char), i_length);
|
psz_fullpath = (char*)calloc(sizeof(char), i_length);
|
||||||
if (psz_fullpath == NULL) {
|
if (psz_fullpath == NULL) {
|
||||||
uprintf("Error allocating file name\n");
|
uprintf("Error allocating file name\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
i_length = _snprintf(psz_fullpath, i_length, "%s%s/%s", psz_extract_dir, psz_path, psz_basename);
|
i_length = safe_sprintf(psz_fullpath, i_length, "%s%s/%s", psz_extract_dir, psz_path, psz_basename);
|
||||||
if (i_length < 0) {
|
if (i_length < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (udf_is_dir(p_udf_dirent)) {
|
if (udf_is_dir(p_udf_dirent)) {
|
||||||
if (!scan_only)
|
if (!scan_only) {
|
||||||
_mkdir(psz_fullpath);
|
_mkdir(psz_fullpath);
|
||||||
|
} else {
|
||||||
|
// Check for an "isolinux\" dir in root (psz_path = "")
|
||||||
|
if ((*psz_path == 0) && (safe_strcmp(psz_basename, "isolinux") == 0))
|
||||||
|
iso_report.has_isolinux = TRUE;
|
||||||
|
}
|
||||||
p_udf_dirent2 = udf_opendir(p_udf_dirent);
|
p_udf_dirent2 = udf_opendir(p_udf_dirent);
|
||||||
if (p_udf_dirent2 != NULL) {
|
if (p_udf_dirent2 != NULL) {
|
||||||
if (udf_extract_files(p_udf, p_udf_dirent2, &psz_fullpath[strlen(psz_extract_dir)]))
|
if (udf_extract_files(p_udf, p_udf_dirent2, &psz_fullpath[strlen(psz_extract_dir)]))
|
||||||
|
@ -103,6 +149,9 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
} else {
|
} else {
|
||||||
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 = "")
|
||||||
|
if ((*psz_path == 0) && (safe_strcmp(psz_basename, "bootmgr") == 0))
|
||||||
|
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;
|
||||||
total_blocks += i_file_length/UDF_BLOCKSIZE;
|
total_blocks += i_file_length/UDF_BLOCKSIZE;
|
||||||
|
@ -111,13 +160,25 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
safe_free(psz_fullpath);
|
safe_free(psz_fullpath);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Replace slashes with backslashes and append the size to the path for UI display
|
||||||
|
nul_pos = safe_strlen(psz_fullpath);
|
||||||
|
for (i=0; i<nul_pos; i++) {
|
||||||
|
if (psz_fullpath[i] == '/')
|
||||||
|
psz_fullpath[i] = '\\';
|
||||||
|
}
|
||||||
|
safe_strcpy(&psz_fullpath[nul_pos], 24, size_to_hr(i_file_length));
|
||||||
uprintf("Extracting: %s\n", psz_fullpath);
|
uprintf("Extracting: %s\n", psz_fullpath);
|
||||||
SetWindowTextU(hISOFileName, psz_fullpath);
|
SetWindowTextU(hISOFileName, psz_fullpath);
|
||||||
fd = fopen(psz_fullpath, "wb");
|
// Remove the appended size for extraction
|
||||||
if (fd == NULL) {
|
psz_fullpath[nul_pos] = 0;
|
||||||
uprintf(" Unable to create file\n");
|
file_handle = CreateFileU(psz_fullpath, GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (file_handle == INVALID_HANDLE_VALUE) {
|
||||||
|
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);
|
||||||
|
@ -126,17 +187,23 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
uprintf(" Error reading UDF file %s\n", &psz_fullpath[strlen(psz_extract_dir)]);
|
uprintf(" Error reading UDF file %s\n", &psz_fullpath[strlen(psz_extract_dir)]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fwrite(buf, (size_t)MIN(i_file_length, i_read), 1, fd);
|
buf_size = (DWORD)MIN(i_file_length, i_read);
|
||||||
if (ferror(fd)) {
|
if (!WriteFile(file_handle, buf, buf_size, &wr_size, NULL) || (buf_size != wr_size)) {
|
||||||
uprintf(" Error writing file\n");
|
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
i_file_length -= i_read;
|
i_file_length -= i_read;
|
||||||
if (nb_blocks++ % PROGRESS_UPDATE == 0)
|
if (nb_blocks++ % PROGRESS_THRESHOLD == 0) {
|
||||||
SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0);
|
SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fclose(fd);
|
// If you have a fast USB 3.0 device, the default Windows buffering does an
|
||||||
fd = NULL;
|
// excellent job at compensating for our small blocks read/writes to max out the
|
||||||
|
// device's bandwidth.
|
||||||
|
// 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
|
||||||
|
// operation. To compensate for this, we create a thread when needed.
|
||||||
|
SAFE_CLOSEHANDLE_THREADED(file_handle);
|
||||||
}
|
}
|
||||||
safe_free(psz_fullpath);
|
safe_free(psz_fullpath);
|
||||||
}
|
}
|
||||||
|
@ -145,30 +212,32 @@ 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);
|
||||||
if (fd != NULL)
|
SAFE_CLOSEHANDLE_THREADED(file_handle);
|
||||||
fclose(fd);
|
|
||||||
safe_free(psz_fullpath);
|
safe_free(psz_fullpath);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
{
|
{
|
||||||
FILE *fd = NULL;
|
HANDLE thid, file_handle = NULL;
|
||||||
|
DWORD buf_size, wr_size;
|
||||||
|
BOOL threaded_close = FALSE;
|
||||||
int i_length, r = 1;
|
int i_length, r = 1;
|
||||||
char psz_fullpath[4096], *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)];
|
||||||
unsigned char buf[ISO_BLOCKSIZE];
|
unsigned char buf[ISO_BLOCKSIZE];
|
||||||
CdioListNode_t* p_entnode;
|
CdioListNode_t* p_entnode;
|
||||||
iso9660_stat_t *p_statbuf;
|
iso9660_stat_t *p_statbuf;
|
||||||
CdioList_t* p_entlist;
|
CdioList_t* p_entlist;
|
||||||
size_t i;
|
size_t i, nul_pos;
|
||||||
lsn_t lsn;
|
lsn_t lsn;
|
||||||
int64_t i_file_length;
|
int64_t i_file_length;
|
||||||
|
|
||||||
if ((p_iso == NULL) || (psz_path == NULL))
|
if ((p_iso == NULL) || (psz_path == NULL))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
i_length = _snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path);
|
i_length = safe_sprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path);
|
||||||
if (i_length < 0)
|
if (i_length < 0)
|
||||||
return 1;
|
return 1;
|
||||||
psz_basename = &psz_fullpath[i_length];
|
psz_basename = &psz_fullpath[i_length];
|
||||||
|
@ -186,13 +255,21 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
continue;
|
continue;
|
||||||
iso9660_name_translate(p_statbuf->filename, psz_basename);
|
iso9660_name_translate(p_statbuf->filename, psz_basename);
|
||||||
if (p_statbuf->type == _STAT_DIR) {
|
if (p_statbuf->type == _STAT_DIR) {
|
||||||
if (!scan_only)
|
if (!scan_only) {
|
||||||
_mkdir(psz_fullpath);
|
_mkdir(psz_fullpath);
|
||||||
|
} else {
|
||||||
|
// Check for an "isolinux\" dir in root (psz_path = "")
|
||||||
|
if ((*psz_path == 0) && (safe_strcmp(psz_basename, "isolinux") == 0))
|
||||||
|
iso_report.has_isolinux = TRUE;
|
||||||
|
}
|
||||||
if (iso_extract_files(p_iso, psz_iso_name))
|
if (iso_extract_files(p_iso, psz_iso_name))
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
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 = "")
|
||||||
|
if ((*psz_path == 0) && (safe_strcmp(psz_basename, "bootmgr") == 0))
|
||||||
|
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;
|
||||||
total_blocks += i_file_length/ISO_BLOCKSIZE;
|
total_blocks += i_file_length/ISO_BLOCKSIZE;
|
||||||
|
@ -200,12 +277,23 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
total_blocks++;
|
total_blocks++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Replace slashes with backslashes and append the size to the path for UI display
|
||||||
|
nul_pos = safe_strlen(psz_fullpath);
|
||||||
|
for (i=0; i<nul_pos; i++) {
|
||||||
|
if (psz_fullpath[i] == '/')
|
||||||
|
psz_fullpath[i] = '\\';
|
||||||
|
}
|
||||||
|
safe_strcpy(&psz_fullpath[nul_pos], 24, size_to_hr(i_file_length));
|
||||||
uprintf("Extracting: %s\n", psz_fullpath);
|
uprintf("Extracting: %s\n", psz_fullpath);
|
||||||
fd = fopen(psz_fullpath, "wb");
|
SetWindowTextU(hISOFileName, psz_fullpath);
|
||||||
if (fd == NULL) {
|
psz_fullpath[nul_pos] = 0;
|
||||||
uprintf(" Unable to create file\n");
|
file_handle = CreateFileU(psz_fullpath, GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (file_handle == INVALID_HANDLE_VALUE) {
|
||||||
|
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);
|
||||||
|
@ -215,24 +303,23 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
psz_iso_name, (long unsigned int)lsn);
|
psz_iso_name, (long unsigned int)lsn);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fwrite(buf, (size_t)MIN(i_file_length, ISO_BLOCKSIZE), 1, fd);
|
buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE);
|
||||||
if (ferror(fd)) {
|
if (!WriteFile(file_handle, buf, buf_size, &wr_size, NULL) || (buf_size != wr_size)) {
|
||||||
uprintf(" Error writing file\n");
|
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
i_file_length -= ISO_BLOCKSIZE;
|
i_file_length -= ISO_BLOCKSIZE;
|
||||||
if (nb_blocks++ % PROGRESS_UPDATE == 0)
|
if (nb_blocks++ % PROGRESS_THRESHOLD == 0) {
|
||||||
SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0);
|
SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fclose(fd);
|
SAFE_CLOSEHANDLE_THREADED(file_handle);
|
||||||
fd = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r = 0;
|
r = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (fd != NULL)
|
SAFE_CLOSEHANDLE_THREADED(file_handle);
|
||||||
fclose(fd);
|
|
||||||
_cdio_list_free(p_entlist, true);
|
_cdio_list_free(p_entlist, true);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -254,10 +341,11 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, bool scan)
|
||||||
psz_extract_dir = dest_dir;
|
psz_extract_dir = dest_dir;
|
||||||
progress_style = GetWindowLong(hISOProgressBar, GWL_STYLE);
|
progress_style = GetWindowLong(hISOProgressBar, GWL_STYLE);
|
||||||
if (scan_only) {
|
if (scan_only) {
|
||||||
uprintf(scan_text);
|
|
||||||
total_blocks = 0;
|
total_blocks = 0;
|
||||||
iso_report.projected_size = 0;
|
iso_report.projected_size = 0;
|
||||||
iso_report.has_4GB_file = FALSE;
|
iso_report.has_4GB_file = FALSE;
|
||||||
|
iso_report.has_bootmgr = FALSE;
|
||||||
|
iso_report.has_isolinux = FALSE;
|
||||||
// Change the Window title and static text
|
// Change the Window title and static text
|
||||||
SetWindowTextU(hISOProgressDlg, scan_text);
|
SetWindowTextU(hISOProgressDlg, scan_text);
|
||||||
SetWindowTextU(hISOFileName, scan_text);
|
SetWindowTextU(hISOFileName, scan_text);
|
||||||
|
@ -282,6 +370,7 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, bool scan)
|
||||||
p_udf = udf_open(src_iso);
|
p_udf = udf_open(src_iso);
|
||||||
if (p_udf == NULL)
|
if (p_udf == NULL)
|
||||||
goto try_iso;
|
goto try_iso;
|
||||||
|
uprintf("Disc image is an UDF image\n");
|
||||||
|
|
||||||
p_udf_root = udf_get_root(p_udf, true, 0);
|
p_udf_root = udf_get_root(p_udf, true, 0);
|
||||||
if (p_udf_root == NULL) {
|
if (p_udf_root == NULL) {
|
||||||
|
@ -297,6 +386,7 @@ try_iso:
|
||||||
uprintf("Unable to open image '%s'.\n", src_iso);
|
uprintf("Unable to open image '%s'.\n", src_iso);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
uprintf("Disc image is an ISO9660 image\n");
|
||||||
r = iso_extract_files(p_iso, "");
|
r = iso_extract_files(p_iso, "");
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -310,6 +400,6 @@ out:
|
||||||
if (p_udf != NULL)
|
if (p_udf != NULL)
|
||||||
udf_close(p_udf);
|
udf_close(p_udf);
|
||||||
if ((r != 0) && (FormatStatus == 0))
|
if ((r != 0) && (FormatStatus == 0))
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT);
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR((scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT));
|
||||||
return r;
|
return (r == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -674,8 +674,10 @@ udf_readdir(udf_dirent_t *p_udf_dirent)
|
||||||
const unsigned int i_len = p_udf_dirent->fid->i_file_id;
|
const unsigned int i_len = p_udf_dirent->fid->i_file_id;
|
||||||
|
|
||||||
if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &p_udf_dirent->fe, p_udf->i_part_start
|
if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, &p_udf_dirent->fe, p_udf->i_part_start
|
||||||
+ p_udf_dirent->fid->icb.loc.lba, 1))
|
+ p_udf_dirent->fid->icb.loc.lba, 1)) {
|
||||||
|
udf_dirent_free(p_udf_dirent);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (strlen(p_udf_dirent->psz_name) < i_len)
|
if (strlen(p_udf_dirent->psz_name) < i_len)
|
||||||
p_udf_dirent->psz_name = (char *)
|
p_udf_dirent->psz_name = (char *)
|
||||||
|
@ -687,6 +689,7 @@ udf_readdir(udf_dirent_t *p_udf_dirent)
|
||||||
}
|
}
|
||||||
return p_udf_dirent;
|
return p_udf_dirent;
|
||||||
}
|
}
|
||||||
|
udf_dirent_free(p_udf_dirent);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
111
src/rufus.c
111
src/rufus.c
|
@ -53,19 +53,20 @@ static BOOL existing_key = FALSE;
|
||||||
HINSTANCE hMainInstance;
|
HINSTANCE hMainInstance;
|
||||||
HWND hMainDialog;
|
HWND hMainDialog;
|
||||||
char szFolderPath[MAX_PATH];
|
char szFolderPath[MAX_PATH];
|
||||||
|
char* iso_path = NULL;
|
||||||
float fScale = 1.0f;
|
float fScale = 1.0f;
|
||||||
int default_fs;
|
int default_fs;
|
||||||
HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses;
|
HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses;
|
||||||
HWND hISOProgressDlg = NULL, hISOProgressBar, hISOFileName;
|
HWND hISOProgressDlg = NULL, hISOProgressBar, hISOFileName;
|
||||||
BOOL bWithFreeDOS, bWithSyslinux;
|
BOOL bWithFreeDOS, bWithSyslinux;
|
||||||
|
|
||||||
|
static HANDLE format_thid = NULL;
|
||||||
static HWND hDeviceTooltip = NULL, hFSTooltip = NULL, hProgress = NULL;
|
static HWND hDeviceTooltip = NULL, hFSTooltip = NULL, hProgress = NULL;
|
||||||
static HWND hDOS = NULL, hSelectISO = NULL, hISOToolTip = NULL;
|
static HWND hDOS = NULL, hSelectISO = NULL, hISOToolTip = NULL;
|
||||||
static HICON hIconDisc;
|
static HICON hIconDisc;
|
||||||
static StrArray DriveID, DriveLabel;
|
static StrArray DriveID, DriveLabel;
|
||||||
static char szTimer[10] = "00:00:00";
|
static char szTimer[12] = "00:00:00";
|
||||||
static unsigned int timer;
|
static unsigned int timer;
|
||||||
static char* iso_path = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following is used to allocate slots within the progress bar
|
* The following is used to allocate slots within the progress bar
|
||||||
|
@ -905,8 +906,10 @@ 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;
|
||||||
PrintStatus(0, FALSE, "Cancelling - please wait...");
|
// if (format_thid != NULL)
|
||||||
uprintf("ISO: USER CANCEL\n");
|
// CancelSynchronousIo(format_thid);
|
||||||
|
PrintStatus(0, FALSE, "Cancelling - This might take a while...");
|
||||||
|
uprintf("Cancelling (ISO)\n");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
case WM_CLOSE: // prevent closure using Alt-F4
|
case WM_CLOSE: // prevent closure using Alt-F4
|
||||||
|
@ -916,16 +919,27 @@ 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
|
||||||
void __cdecl ISOScanThread(void* param)
|
DWORD WINAPI ISOScanThread(LPVOID param)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
// ExtractISO(ISO_IMAGE, ISO_DEST, TRUE);
|
|
||||||
PrintStatus(0, TRUE, "Scanning ISO image...\n");
|
PrintStatus(0, TRUE, "Scanning ISO image...\n");
|
||||||
ExtractISO(iso_path, "", TRUE);
|
if (!ExtractISO(iso_path, "", TRUE)) {
|
||||||
uprintf("Projected size: %lld\nHas 4GB: %s\n", iso_report.projected_size, iso_report.has_4GB_file?"TRUE":"FALSE");
|
PrintStatus(0, TRUE, "Failed to scan ISO image.");
|
||||||
for (i=safe_strlen(iso_path); (i>=0)&&(iso_path[i] != '\\'); i--);
|
goto out;
|
||||||
PrintStatus(0, TRUE, "Using ISO: '%s'\n", &iso_path[i+1]);
|
}
|
||||||
_endthread();
|
uprintf("ISO size: %lld bytes, 4GB:%c, bootmgr:%c, isolinux:%c\n", iso_report.projected_size,
|
||||||
|
iso_report.has_4GB_file?'Y':'N', iso_report.has_bootmgr?'Y':'N', iso_report.has_isolinux?'Y':'N');
|
||||||
|
if (!iso_report.has_bootmgr) {
|
||||||
|
MessageBoxU(hMainDialog, "This version of Rufus supports only\n"
|
||||||
|
"ISO images that rely on 'bootmgr' - sorry.", "Unsupported ISO", MB_OK|MB_ICONINFORMATION);
|
||||||
|
safe_free(iso_path);
|
||||||
|
} else {
|
||||||
|
for (i=safe_strlen(iso_path); (i>=0)&&(iso_path[i] != '\\'); i--);
|
||||||
|
PrintStatus(0, TRUE, "Using ISO: '%s'\n", &iso_path[i+1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
ExitThread(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to obtain a handle to a DLL
|
// Helper function to obtain a handle to a DLL
|
||||||
|
@ -965,6 +979,10 @@ void InitDialog(HWND hDlg)
|
||||||
HICON hSmallIcon, hBigIcon;
|
HICON hSmallIcon, hBigIcon;
|
||||||
char tmp[128];
|
char tmp[128];
|
||||||
|
|
||||||
|
#ifdef RUFUS_TEST
|
||||||
|
ShowWindow(GetDlgItem(hDlg, IDC_TEST), SW_SHOW);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Quite a burden to carry around as parameters
|
// Quite a burden to carry around as parameters
|
||||||
hMainDialog = hDlg;
|
hMainDialog = hDlg;
|
||||||
hDeviceList = GetDlgItem(hDlg, IDC_DEVICE);
|
hDeviceList = GetDlgItem(hDlg, IDC_DEVICE);
|
||||||
|
@ -1009,8 +1027,7 @@ void InitDialog(HWND hDlg)
|
||||||
IGNORE_RETVAL(ComboBox_SetCurSel(hNBPasses, 1));
|
IGNORE_RETVAL(ComboBox_SetCurSel(hNBPasses, 1));
|
||||||
// Fill up the DOS type dropdown
|
// Fill up the DOS type dropdown
|
||||||
IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "MS-DOS"), DT_WINME));
|
IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "MS-DOS"), DT_WINME));
|
||||||
IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "ISO"), DT_ISO));
|
IGNORE_RETVAL(ComboBox_SetCurSel(hDOSType, DT_WINME));
|
||||||
IGNORE_RETVAL(ComboBox_SetCurSel(hDOSType, bWithFreeDOS?DT_FREEDOS:DT_WINME));
|
|
||||||
// Create the string array
|
// Create the string array
|
||||||
StrArrayCreate(&DriveID, MAX_DRIVES);
|
StrArrayCreate(&DriveID, MAX_DRIVES);
|
||||||
StrArrayCreate(&DriveLabel, MAX_DRIVES);
|
StrArrayCreate(&DriveLabel, MAX_DRIVES);
|
||||||
|
@ -1044,13 +1061,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
int nDeviceIndex, fs, dt;
|
int nDeviceIndex, fs, dt;
|
||||||
DWORD DeviceNum;
|
DWORD DeviceNum;
|
||||||
char str[MAX_PATH], tmp[128];
|
char str[MAX_PATH], tmp[128];
|
||||||
static uintptr_t format_thid = -1L;
|
|
||||||
static UINT uDOSChecked = BST_CHECKED;
|
static UINT uDOSChecked = BST_CHECKED;
|
||||||
|
|
||||||
switch (message) {
|
switch (message) {
|
||||||
|
|
||||||
case WM_DEVICECHANGE:
|
case WM_DEVICECHANGE:
|
||||||
if ( (format_thid == -1L) &&
|
if ( (format_thid == NULL) &&
|
||||||
((wParam == DBT_DEVICEARRIVAL) || (wParam == DBT_DEVICEREMOVECOMPLETE)) ) {
|
((wParam == DBT_DEVICEARRIVAL) || (wParam == DBT_DEVICEREMOVECOMPLETE)) ) {
|
||||||
GetUSBDevices();
|
GetUSBDevices();
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
|
@ -1079,15 +1095,16 @@ 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:
|
||||||
if (format_thid != -1L) {
|
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 != -1L) {
|
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("USER CANCEL\n");
|
uprintf("Cancelling (General)\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
|
@ -1103,19 +1120,6 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
break;
|
break;
|
||||||
#ifdef RUFUS_TEST
|
#ifdef RUFUS_TEST
|
||||||
case IDC_TEST:
|
case IDC_TEST:
|
||||||
FormatStatus = 0;
|
|
||||||
// You'd think that Windows would let you instantiate a modeless dialog wherever
|
|
||||||
// but you'd be wrong. It has to be done in the main callback!
|
|
||||||
if (!IsWindow(hISOProgressDlg)) {
|
|
||||||
hISOProgressDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_ISO_EXTRACT),
|
|
||||||
hDlg, (DLGPROC)ISOProc);
|
|
||||||
// The window is not visible by default but takes focus => restore it
|
|
||||||
SetFocus(hDlg);
|
|
||||||
}
|
|
||||||
if (_beginthread(ISOScanThread, 0, NULL) == -1L) {
|
|
||||||
uprintf("Unable to start ISO scanning thread");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case IDC_DEVICE:
|
case IDC_DEVICE:
|
||||||
|
@ -1150,7 +1154,10 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
if (bWithSyslinux)
|
if (bWithSyslinux)
|
||||||
IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "Syslinux"), DT_SYSLINUX));
|
IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "Syslinux"), DT_SYSLINUX));
|
||||||
}
|
}
|
||||||
IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "ISO"), DT_ISO));
|
if (fs == FS_NTFS) {
|
||||||
|
// Only allow ISO with NTFS for the time being
|
||||||
|
IGNORE_RETVAL(ComboBox_SetItemData(hDOSType, ComboBox_AddStringU(hDOSType, "ISO..."), DT_ISO));
|
||||||
|
}
|
||||||
IGNORE_RETVAL(ComboBox_SetCurSel(hDOSType, (bWithFreeDOS && (fs != FS_NTFS))?1:0));
|
IGNORE_RETVAL(ComboBox_SetCurSel(hDOSType, (bWithFreeDOS && (fs != FS_NTFS))?1:0));
|
||||||
if (!IsWindowEnabled(hDOS)) {
|
if (!IsWindowEnabled(hDOS)) {
|
||||||
EnableWindow(hDOS, TRUE);
|
EnableWindow(hDOS, TRUE);
|
||||||
|
@ -1189,18 +1196,31 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
// The window is not visible by default but takes focus => restore it
|
// The window is not visible by default but takes focus => restore it
|
||||||
SetFocus(hDlg);
|
SetFocus(hDlg);
|
||||||
}
|
}
|
||||||
if (_beginthread(ISOScanThread, 0, NULL) == -1L) {
|
if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, 0) == NULL) {
|
||||||
uprintf("Unable to start ISO scanning thread");
|
uprintf("Unable to start ISO scanning thread");
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD);
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDC_START:
|
case IDC_START:
|
||||||
if (format_thid != -1L) {
|
if (format_thid != NULL) {
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
}
|
}
|
||||||
FormatStatus = 0;
|
FormatStatus = 0;
|
||||||
nDeviceIndex = ComboBox_GetCurSel(hDeviceList);
|
nDeviceIndex = ComboBox_GetCurSel(hDeviceList);
|
||||||
if (nDeviceIndex != CB_ERR) {
|
if (nDeviceIndex != CB_ERR) {
|
||||||
|
if (ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)) == DT_ISO) {
|
||||||
|
if (iso_path == NULL) {
|
||||||
|
MessageBoxA(hMainDialog, "Please click on the disc button to select a bootable ISO,\n"
|
||||||
|
"or unselect the \"Create bootable disk...\" checkbox.",
|
||||||
|
"No ISO image selected...", MB_OK|MB_ICONERROR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (iso_report.projected_size > (uint64_t)SelectedDrive.DiskSize) {
|
||||||
|
MessageBoxA(hMainDialog, "This ISO image is too big "
|
||||||
|
"for the selected target.", "ISO image too big...", MB_OK|MB_ICONERROR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
GetWindowTextA(hDeviceList, tmp, sizeof(tmp));
|
GetWindowTextA(hDeviceList, tmp, sizeof(tmp));
|
||||||
safe_sprintf(str, sizeof(str), "WARNING: ALL DATA ON DEVICE %s\r\nWILL BE DESTROYED.\r\n"
|
safe_sprintf(str, sizeof(str), "WARNING: ALL DATA ON DEVICE %s\r\nWILL BE DESTROYED.\r\n"
|
||||||
"To continue with this operation, click OK. To quit click CANCEL.", tmp);
|
"To continue with this operation, click OK. To quit click CANCEL.", tmp);
|
||||||
|
@ -1216,8 +1236,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
// The window is not visible by default but takes focus => restore it
|
// The window is not visible by default but takes focus => restore it
|
||||||
SetFocus(hDlg);
|
SetFocus(hDlg);
|
||||||
}
|
}
|
||||||
format_thid = _beginthread(FormatThread, 0, (void*)(uintptr_t)DeviceNum);
|
format_thid = CreateThread(NULL, 0, FormatThread, (LPVOID)(uintptr_t)DeviceNum, 0, NULL);
|
||||||
if (format_thid == -1L) {
|
if (format_thid == NULL) {
|
||||||
uprintf("Unable to start formatting thread");
|
uprintf("Unable to start formatting thread");
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD);
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD);
|
||||||
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
|
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
|
||||||
|
@ -1236,16 +1256,14 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
if (format_thid != -1L) {
|
if (format_thid != NULL) {
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
}
|
}
|
||||||
DestroyAllTooltips();
|
|
||||||
safe_free(iso_path);
|
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UM_FORMAT_COMPLETED:
|
case UM_FORMAT_COMPLETED:
|
||||||
format_thid = -1L;
|
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 if active
|
||||||
|
@ -1256,7 +1274,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
||||||
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.");
|
Notification(MSG_INFO, "Cancelled", "Operation cancelled by the user.\n"
|
||||||
|
"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));
|
||||||
|
@ -1321,10 +1340,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
MessageBoxA(NULL, "Could not create Window", "DialogBox failure", MB_ICONSTOP);
|
MessageBoxA(NULL, "Could not create Window", "DialogBox failure", MB_ICONSTOP);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
// CenterDialog(hDlg);
|
|
||||||
#ifndef RUFUS_TEST
|
|
||||||
ShowWindow(GetDlgItem(hDlg, IDC_TEST), SW_HIDE);
|
|
||||||
#endif
|
|
||||||
ShowWindow(hDlg, SW_SHOWNORMAL);
|
ShowWindow(hDlg, SW_SHOWNORMAL);
|
||||||
UpdateWindow(hDlg);
|
UpdateWindow(hDlg);
|
||||||
|
|
||||||
|
@ -1346,6 +1361,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
DestroyAllTooltips();
|
||||||
|
safe_free(iso_path);
|
||||||
#ifdef DISABLE_AUTORUN
|
#ifdef DISABLE_AUTORUN
|
||||||
SetLGP(TRUE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutorun", 0);
|
SetLGP(TRUE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutorun", 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
11
src/rufus.h
11
src/rufus.h
|
@ -27,12 +27,6 @@
|
||||||
|
|
||||||
/* 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 ISO_DEST "D:/tmp/iso"
|
|
||||||
//#define ISO_IMAGE "D:\\Incoming\\Windows 8 Preview\\WindowsDeveloperPreview-64bit-English-Developer.iso"
|
|
||||||
//#define ISO_IMAGE "D:\\fd11src.iso", "D:/tmp/iso"
|
|
||||||
//#define ISO_IMAGE "D:\\Incoming\\GRMSDKX_EN_DVD.iso"
|
|
||||||
//#define ISO_IMAGE "D:\\Incoming\\en_windows_driver_kit_3790.iso"
|
|
||||||
//#define ISO_IMAGE "D:\\Incoming\\en_windows_7_ultimate_with_sp1_x64_dvd_618240.iso"
|
|
||||||
|
|
||||||
#define STR_NO_LABEL "NO_LABEL"
|
#define STR_NO_LABEL "NO_LABEL"
|
||||||
#define RUFUS_CANCELBOX_TITLE "Rufus - Cancellation"
|
#define RUFUS_CANCELBOX_TITLE "Rufus - Cancellation"
|
||||||
|
@ -152,6 +146,8 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t projected_size;
|
uint64_t projected_size;
|
||||||
BOOL has_4GB_file;
|
BOOL has_4GB_file;
|
||||||
|
BOOL has_bootmgr;
|
||||||
|
BOOL has_isolinux;
|
||||||
} RUFUS_ISO_REPORT;
|
} RUFUS_ISO_REPORT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -163,6 +159,7 @@ extern HWND hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses;
|
||||||
extern HWND hISOProgressDlg, hISOProgressBar, hISOFileName;
|
extern HWND hISOProgressDlg, hISOProgressBar, hISOFileName;
|
||||||
extern float fScale;
|
extern float fScale;
|
||||||
extern char szFolderPath[MAX_PATH];
|
extern char szFolderPath[MAX_PATH];
|
||||||
|
extern char* iso_path;
|
||||||
extern DWORD FormatStatus;
|
extern DWORD FormatStatus;
|
||||||
extern RUFUS_DRIVE_INFO SelectedDrive;
|
extern RUFUS_DRIVE_INFO SelectedDrive;
|
||||||
extern const int nb_steps[FS_MAX];
|
extern const int nb_steps[FS_MAX];
|
||||||
|
@ -187,7 +184,7 @@ extern BOOL Notification(int type, char* title, char* format, ...);
|
||||||
extern BOOL ExtractDOS(const char* path);
|
extern BOOL ExtractDOS(const char* path);
|
||||||
extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan);
|
extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan);
|
||||||
extern BOOL InstallSyslinux(DWORD num, const char* drive_name);
|
extern BOOL InstallSyslinux(DWORD num, const char* drive_name);
|
||||||
extern void __cdecl FormatThread(void* param);
|
DWORD WINAPI FormatThread(void* param);
|
||||||
extern BOOL CreatePartition(HANDLE hDrive);
|
extern BOOL CreatePartition(HANDLE hDrive);
|
||||||
extern HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive);
|
extern HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive);
|
||||||
extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label);
|
extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label);
|
||||||
|
|
29
src/rufus.rc
29
src/rufus.rc
|
@ -8,7 +8,7 @@
|
||||||
// Generated from the TEXTINCLUDE 2 resource.
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
//
|
//
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#ifndef __GNUC__
|
#ifndef __MINGW32__
|
||||||
#include "../ms-config.h"
|
#include "../ms-config.h"
|
||||||
#endif
|
#endif
|
||||||
#ifndef IDC_STATIC
|
#ifndef IDC_STATIC
|
||||||
|
@ -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.7.126"
|
CAPTION "Rufus v1.0.7.127"
|
||||||
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
|
||||||
|
@ -56,7 +56,7 @@ BEGIN
|
||||||
CONTROL "",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,210,189,9
|
CONTROL "",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,210,189,9
|
||||||
COMBOBOX IDC_DOSTYPE,118,183,45,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
COMBOBOX IDC_DOSTYPE,118,183,45,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
COMBOBOX IDC_NBPASSES,118,159,45,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
COMBOBOX IDC_NBPASSES,118,159,45,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
PUSHBUTTON "Test",IDC_TEST,62,236,20,14
|
PUSHBUTTON "Test",IDC_TEST,62,236,20,14,NOT WS_VISIBLE
|
||||||
PUSHBUTTON "...",IDC_SELECT_ISO,168,182,23,14,BS_ICON | NOT WS_VISIBLE
|
PUSHBUTTON "...",IDC_SELECT_ISO,168,182,23,14,BS_ICON | NOT WS_VISIBLE
|
||||||
END
|
END
|
||||||
|
|
||||||
|
@ -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.7 (Build 126)",IDC_STATIC,46,19,78,8
|
LTEXT "Version 1.0.7 (Build 127)",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
|
||||||
|
@ -92,14 +92,14 @@ BEGIN
|
||||||
DEFPUSHBUTTON "Close",IDCANCEL,211,44,50,14
|
DEFPUSHBUTTON "Close",IDCANCEL,211,44,50,14
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_ISO_EXTRACT DIALOGEX 0, 0, 262, 73
|
IDD_ISO_EXTRACT DIALOGEX 0, 0, 262, 66
|
||||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
|
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
|
||||||
CAPTION "Extracting Files..."
|
CAPTION "Copying ISO files..."
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "",IDC_ISO_FILENAME,14,9,232,14
|
LTEXT "",IDC_ISO_FILENAME,8,10,246,13,SS_PATHELLIPSIS
|
||||||
CONTROL "",IDC_ISO_PROGRESS,"msctls_progress32",WS_BORDER,14,32,231,8
|
CONTROL "",IDC_ISO_PROGRESS,"msctls_progress32",WS_BORDER,7,26,247,8
|
||||||
PUSHBUTTON "Abort",IDC_ISO_ABORT,112,50,50,14
|
PUSHBUTTON "Cancel",IDC_ISO_ABORT,111,43,50,14
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_LICENSE DIALOGEX 0, 0, 335, 205
|
IDD_LICENSE DIALOGEX 0, 0, 335, 205
|
||||||
|
@ -126,7 +126,7 @@ END
|
||||||
2 TEXTINCLUDE
|
2 TEXTINCLUDE
|
||||||
BEGIN
|
BEGIN
|
||||||
"#include <windows.h>\r\n"
|
"#include <windows.h>\r\n"
|
||||||
"#ifndef __GNUC__\r\n"
|
"#ifndef __MINGW32__\r\n"
|
||||||
"#include ""../ms-config.h""\r\n"
|
"#include ""../ms-config.h""\r\n"
|
||||||
"#endif\r\n"
|
"#endif\r\n"
|
||||||
"#ifndef IDC_STATIC\r\n"
|
"#ifndef IDC_STATIC\r\n"
|
||||||
|
@ -207,6 +207,7 @@ BEGIN
|
||||||
|
|
||||||
IDD_ISO_EXTRACT, DIALOG
|
IDD_ISO_EXTRACT, DIALOG
|
||||||
BEGIN
|
BEGIN
|
||||||
|
BOTTOMMARGIN, 65
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_LICENSE, DIALOG
|
IDD_LICENSE, DIALOG
|
||||||
|
@ -222,8 +223,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,0,7,126
|
FILEVERSION 1,0,7,127
|
||||||
PRODUCTVERSION 1,0,7,126
|
PRODUCTVERSION 1,0,7,127
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -240,13 +241,13 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "akeo.ie"
|
VALUE "CompanyName", "akeo.ie"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "1.0.7.126"
|
VALUE "FileVersion", "1.0.7.127"
|
||||||
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.7.126"
|
VALUE "ProductVersion", "1.0.7.127"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -213,7 +213,7 @@ const char* StrError(DWORD error_code)
|
||||||
case ERROR_PARTITION_FAILURE:
|
case ERROR_PARTITION_FAILURE:
|
||||||
return "Error while partitioning drive";
|
return "Error while partitioning drive";
|
||||||
case ERROR_CANNOT_COPY:
|
case ERROR_CANNOT_COPY:
|
||||||
return "Could not copy MS-DOS files";
|
return "Could not copy files to target drive";
|
||||||
case ERROR_CANCELLED:
|
case ERROR_CANCELLED:
|
||||||
return "Cancelled by user";
|
return "Cancelled by user";
|
||||||
case ERROR_CANT_START_THREAD:
|
case ERROR_CANT_START_THREAD:
|
||||||
|
@ -224,6 +224,9 @@ const char* StrError(DWORD error_code)
|
||||||
return "ISO image scan failure";
|
return "ISO image scan failure";
|
||||||
case ERROR_ISO_EXTRACT:
|
case ERROR_ISO_EXTRACT:
|
||||||
return "ISO image scan failure";
|
return "ISO image scan failure";
|
||||||
|
case ERROR_CANT_REMOUNT_VOLUME:
|
||||||
|
return "Unable to remount volume. You may have to use the\n"
|
||||||
|
"mountvol.exe command to make your device accessible again";
|
||||||
default:
|
default:
|
||||||
uprintf("Unknown error: %08X\n", error_code);
|
uprintf("Unknown error: %08X\n", error_code);
|
||||||
SetLastError(error_code);
|
SetLastError(error_code);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue