[togo] Add Windows To Go support - part 2

* Enable the creation of MSR and MS EFI partition in GPT mode
* Closes #432
This commit is contained in:
Pete Batard 2015-01-20 02:56:17 +00:00
parent ec761dfb41
commit ed9fae7c81
5 changed files with 205 additions and 51 deletions

View File

@ -45,6 +45,10 @@ const GUID PARTITION_BASIC_DATA_GUID =
const GUID PARTITION_MSFT_RESERVED_GUID =
{ 0xe3c9e316L, 0x0b5c, 0x4db8, {0x81, 0x7d, 0xf9, 0x2d, 0xf0, 0x02, 0x15, 0xae} };
#endif
#if !defined(PARTITION_SYSTEM_GUID)
const GUID PARTITION_SYSTEM_GUID =
{ 0xc12a7328L, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} };
#endif
/*
* Globals
@ -102,7 +106,7 @@ BOOL GetAutoMount(BOOL* enabled)
*/
#define CheckDriveIndex(DriveIndex) do { \
if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) { \
uprintf("WARNING: Bad index value. Please check the code!\n"); \
uprintf("ERROR: Bad index value. Please check the code!\n"); \
goto out; \
} \
DriveIndex -= DRIVE_INDEX_MIN; } while (0)
@ -403,7 +407,7 @@ static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT*
hDrive = CreateFileA(logical_drive, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDrive == INVALID_HANDLE_VALUE) {
uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString());
// uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString());
continue;
}
@ -684,7 +688,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
return 0;
}
if (DiskGeometry->Geometry.BytesPerSector < 512) {
suprintf("WARNING: Drive 0x%02x reports a sector size of %d - Correcting to 512 bytes.\n",
suprintf("Warning: Drive 0x%02x reports a sector size of %d - Correcting to 512 bytes.\n",
DriveIndex, DiskGeometry->Geometry.BytesPerSector);
DiskGeometry->Geometry.BytesPerSector = 512;
}
@ -863,6 +867,102 @@ BOOL MountVolume(char* drive_name, char *drive_guid)
return TRUE;
}
/*
* Mount partition #part_nr, residing on the same disk as drive_name to an available
* drive letter. Returns the newly allocated drive string.
* We need to do this because, for instance, EFI System partitions are not assigned
* Volume GUIDs by the OS, and we need to have a letter assigned, for when we invoke
* bcdtool for Windows To Go. All in all, the process looks like this:
* 1. F: = \Device\HarddiskVolume9 (SINGLE LOOKUP)
* 2. Harddisk5Partition1 = \Device\HarddiskVolume9 (FULL LOOKUP)
* 3. Harddisk5Partition2 = \Device\HarddiskVolume10 (SINGLE LOOKUP)
* 4. DefineDosDevice(letter, \Device\HarddiskVolume10)
*/
char* AltMountVolume(const char* drive_name, uint8_t part_nr)
{
static char mounted_drive[] = "?:";
const size_t bufsize = 65536;
char *buffer = NULL, *p, target[2][MAX_PATH], *ret = NULL;
int i;
mounted_drive[0] = GetUnusedDriveLetter();
if (mounted_drive[0] == 0) {
uprintf("Could not find an unused drive letter");
goto out;
}
target[0][0] = 0;
// Convert our drive letter to something like "\Device\HarddiskVolume9"
if (!QueryDosDeviceA(drive_name, target[0], MAX_PATH) && (strlen(target[0]) == 0)) {
uprintf("Could not get the DOS device name for '%s': %s", drive_name, WindowsErrorString());
goto out;
}
// Now parse the whole DOS device list to find the 'Harddisk#Partition#' that matches the above
// TODO: realloc if someone ever manages to burst through 64K of DOS devices
buffer = malloc(bufsize);
if (buffer == NULL)
goto out;
buffer[0] = 0;
if (!QueryDosDeviceA(NULL, buffer, bufsize)) {
uprintf("Could not get the DOS device list: %s", WindowsErrorString());
goto out;
}
p = buffer;
while (strlen(p) != 0) {
if ((strncmp("Harddisk", p, 8) == 0) && (strstr(&p[9], "Partition") != NULL)) {
target[1][0] = 0;
if (QueryDosDeviceA(p, target[1], MAX_PATH) && (strlen(target[1]) != 0))
if ((strcmp(target[1], target[0]) == 0) && (p[1] != ':'))
break;
}
p += strlen(p) + 1;
}
i = strlen(p);
if (i == 0) {
uprintf("Could not find partition mapping for %s", target[0]);
goto out;
}
while ((--i > 0) && (isdigit(p[i])));
p[++i] = '0' + part_nr;
p[++i] = 0;
target[0][0] = 0;
if (!QueryDosDeviceA(p, target[0], MAX_PATH) && (strlen(target[0]) == 0)) {
uprintf("Could not get DOS device name for partition '%s': %s", drive_name, WindowsErrorString());
goto out;
}
if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH | DDD_NO_BROADCAST_SYSTEM, mounted_drive, target[0])) {
uprintf("Could not mount '%s' to '%s': %s", target[0], mounted_drive, WindowsErrorString());
goto out;
}
uprintf("Successfully mounted '%s' (USB partition %d) as '%s'", target[0], part_nr, mounted_drive);
ret = mounted_drive;
out:
safe_free(buffer);
return ret;
}
/*
* Unmount a volume that was mounted by AltmountVolume()
*/
BOOL AltUnmountVolume(const char* drive_name)
{
if (!DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_NO_BROADCAST_SYSTEM, drive_name, NULL)) {
uprintf("Could not unmount '%s': %s", drive_name, WindowsErrorString());
return FALSE;
}
uprintf("Successfully unmounted '%s'", drive_name);
return TRUE;
}
/*
* Issue a complete remount of the volume
*/
@ -909,7 +1009,7 @@ typedef struct _DRIVE_LAYOUT_INFORMATION_EX4 {
* copy it got from the last IOCTL, and ignores your changes until you replug the drive
* or issue an IOCTL_DISK_UPDATE_PROPERTIES.
*/
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, BOOL add_uefi_togo)
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, uint8_t extra_partitions)
{
const char* PartitionTypeName[2] = { "MBR", "GPT" };
unsigned char* buffer;
@ -917,12 +1017,11 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0};
BOOL r;
DWORD i, size, bufsize, pn = 0;
LONGLONG size_in_sectors, extra_part_size_in_tracks = 0;
BOOL add_msr = FALSE; //TRUE;
LONGLONG main_part_size_in_sectors, extra_part_size_in_tracks = 0;
PrintInfoDebug(0, MSG_238, PartitionTypeName[partition_style]);
if (uefi_togo_size == 0)
if ((extra_partitions & XP_UEFI_TOGO) && (uefi_togo_size == 0))
uefi_togo_size = GetResourceSize(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_TOGO), _RT_RCDATA, "uefi-togo.img");
// Compute the start offset of our first partition
@ -936,7 +1035,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
}
// If required, set the MSR partition (GPT only - must be created before the data part)
if ((partition_style == PARTITION_STYLE_GPT) && (add_msr)) {
if ((partition_style == PARTITION_STYLE_GPT) && (extra_partitions & XP_MSR)) {
uprintf("Adding MSR partition");
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = 128*1024*1024;
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_MSFT_RESERVED_GUID;
@ -948,24 +1047,27 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
}
// Set our main data partition
size_in_sectors = (SelectedDrive.DiskSize - DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart) /
main_part_size_in_sectors = (SelectedDrive.DiskSize - DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart) /
// Need 33 sectors at the end for secondary GPT
SelectedDrive.Geometry.BytesPerSector - ((partition_style == PARTITION_STYLE_GPT)?33:0);
// Adjust the size according to extra partitions
if ((add_uefi_togo) || ((partition_style == PARTITION_STYLE_MBR) && (IsChecked(IDC_EXTRA_PARTITION)))) {
if (add_uefi_togo) {
extra_part_size_in_tracks = (MIN_EXTRA_PART_SIZE + SelectedDrive.Geometry.SectorsPerTrack - 1) /
SelectedDrive.Geometry.SectorsPerTrack;
if (extra_partitions) {
if (extra_partitions & (XP_UEFI_TOGO | XP_EFI)) {
// TODO: this will explode to 800MB instead of 100MB on 4K sectors...
extra_part_size_in_tracks = ((MIN_EXTRA_PART_SIZE*((extra_partitions & XP_EFI)?100:1))
+ SelectedDrive.Geometry.SectorsPerTrack - 1) / SelectedDrive.Geometry.SectorsPerTrack;
} else {
extra_part_size_in_tracks = 1; // One track for the extra part in non togo mode
extra_part_size_in_tracks = 1; // One track for the extra partition
}
uprintf("Reserving %d tracks for extra partition", extra_part_size_in_tracks);
size_in_sectors = ((size_in_sectors / SelectedDrive.Geometry.SectorsPerTrack) - extra_part_size_in_tracks) *
SelectedDrive.Geometry.SectorsPerTrack;
if (size_in_sectors <= 0)
uprintf("Reserving %lld tracks (%s) for extra partition", extra_part_size_in_tracks,
SizeToHumanReadable(extra_part_size_in_tracks * SelectedDrive.Geometry.SectorsPerTrack *
SelectedDrive.Geometry.BytesPerSector, TRUE, FALSE));
main_part_size_in_sectors = ((main_part_size_in_sectors / SelectedDrive.Geometry.SectorsPerTrack) -
extra_part_size_in_tracks) * SelectedDrive.Geometry.SectorsPerTrack;
if (main_part_size_in_sectors <= 0)
return FALSE;
}
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = size_in_sectors * SelectedDrive.Geometry.BytesPerSector;
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = main_part_size_in_sectors * SelectedDrive.Geometry.BytesPerSector;
if (partition_style == PARTITION_STYLE_MBR) {
DriveLayoutEx.PartitionEntry[pn].Mbr.BootIndicator = IsChecked(IDC_BOOT);
DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack;
@ -994,24 +1096,23 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
pn++;
// Set the optional extra partition
if (IsChecked(IDC_EXTRA_PARTITION) || (add_uefi_togo)) {
if (extra_partitions) {
// Should end on a track boundary
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = (add_uefi_togo)?uefi_togo_size:
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = (extra_partitions & XP_UEFI_TOGO)?uefi_togo_size:
extra_part_size_in_tracks * SelectedDrive.Geometry.SectorsPerTrack * SelectedDrive.Geometry.BytesPerSector;
if (partition_style == PARTITION_STYLE_GPT) {
if (add_uefi_togo) // already set to UNUSED GUID (000...000) otherwise
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_BASIC_DATA_GUID;
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_SYSTEM_GUID;
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, (add_uefi_togo)?L"UEFI:TOGO":L"Rufus Extra Partition");
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, (extra_partitions & XP_UEFI_TOGO)?L"UEFI:TOGO":L"EFI system partition");
} else {
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = (add_uefi_togo)?0x01:RUFUS_EXTRA_PARTITION_TYPE;
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = (extra_partitions & XP_UEFI_TOGO)?0x01:RUFUS_EXTRA_PARTITION_TYPE;
DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack;
}
// We need to write the TOGO partition before we refresh the disk
if (add_uefi_togo) {
if (extra_partitions & XP_UEFI_TOGO) {
uprintf("Writing UEFI:TOGO partition...");
if (!SetFilePointerEx(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, NULL, FILE_BEGIN)) {
uprintf("Unable to set position");

View File

@ -30,6 +30,10 @@
#define IOCTL_MOUNTMGR_SET_AUTO_MOUNT \
CTL_CODE(MOUNTMGRCONTROLTYPE, 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define XP_MSR 0x01
#define XP_EFI 0x02
#define XP_UEFI_TOGO 0x04
/* We need a redef of these MS structure */
typedef struct {
DWORD DeviceType;
@ -62,8 +66,10 @@ BOOL AnalyzePBR(HANDLE hLogicalVolume);
BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSystemNameSize, BOOL bSilent);
BOOL UnmountVolume(HANDLE hDrive);
BOOL MountVolume(char* drive_name, char *drive_guid);
BOOL AltUnmountVolume(const char* drive_name);
char* AltMountVolume(const char* drive_name, uint8_t part_nr);
BOOL RemountVolume(char* drive_name);
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, BOOL add_uefi_togo);
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, uint8_t extra_partitions);
BOOL DeletePartitions(HANDLE hDrive);
BOOL RefreshDriveLayout(HANDLE hDrive);
const char* GetPartitionType(BYTE Type);

View File

@ -1226,15 +1226,24 @@ out:
}
// http://technet.microsoft.com/en-ie/library/jj721578.aspx
static BOOL SetupWinToGo(const char* drive_name)
BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi)
{
char san_policy_path[] = "?:\\san_policy.xml", unattend_path[] = "?:\\Windows\\System32\\sysprep\\unattend.xml";
char *mounted_iso, image[128], cmd[128];
char *mounted_iso, *ms_efi, image[128], cmd[128];
wchar_t wVolumeName[] = L"?:";
unsigned char *buffer;
DWORD bufsize;
FILE* fd;
PF_DECL(FormatEx);
PF_INIT(FormatEx, Fmifs);
uprintf("Windows To Go mode selected");
if ((use_ms_efi) && (SelectedDrive.Geometry.MediaType != FixedMedia)) {
// Arthur's Theme: "♫ I know it's stupid... but it's true. ♫"
uprintf("Cannot set 'Windows To Go' for a GPT target unless it is a fixed drive");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
return FALSE;
}
// First, we need to access the install.wim image, that resides on the ISO
mounted_iso = MountISO(image_path);
@ -1256,15 +1265,46 @@ static BOOL SetupWinToGo(const char* drive_name)
}
UnMountISO();
uprintf("Setting up boot for Windows To Go...");
static_sprintf(cmd, "%C:\\Windows\\System32\\bcdboot.exe %C:\\Windows /f ALL /s %C:",
drive_name[0], drive_name[0], drive_name[0]);
if (use_ms_efi) {
uprintf("Setting up MS EFI system partition");
if (pfFormatEx == NULL)
return FALSE;
ms_efi = AltMountVolume(drive_name, 3); // MSR, main, EFI
if (ms_efi == NULL) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_ASSIGN_LETTER);
return FALSE;
}
fs_index = 0;
task_number = 0;
wVolumeName[0] = ms_efi[0];
// Boy do you *NOT* want to specify a label here, and spend
// HOURS figuring out why your EFI partition cannot boot...
pfFormatEx(wVolumeName, SelectedDrive.Geometry.MediaType, L"FAT32", L"",
TRUE, 1024, FormatExCallback);
if (IS_ERROR(FormatStatus)) {
uprintf("Failed to format EFI partition");
AltUnmountVolume(ms_efi);
return FALSE;
}
}
// TODO: Don't use ALL but adjust to what we effectively support
static_sprintf(cmd, "%s\\Windows\\System32\\bcdboot.exe %s\\Windows /f ALL /s %s",
drive_name, drive_name, (use_ms_efi)?ms_efi:drive_name);
uprintf("Enabling boot: '%s'", cmd);
if (RunCommand(cmd, NULL, TRUE) != 0) {
// Fatal, as the UFD is unlikely to boot then
uprintf("Command '%s' failed to run", cmd);
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);
if (use_ms_efi)
AltUnmountVolume(ms_efi);
return FALSE;
}
if (use_ms_efi) {
Sleep(200);
AltUnmountVolume(ms_efi);
}
UpdateProgress(OP_DOS, 99.0f);
// The following are non fatal if they fail
@ -1279,7 +1319,7 @@ static BOOL SetupWinToGo(const char* drive_name)
fclose(fd);
} else {
fclose(fd);
static_sprintf(cmd, "dism /Image:%C:\\ /Apply-Unattend:%s", drive_name[0], san_policy_path);
static_sprintf(cmd, "dism /Image:%s\\ /Apply-Unattend:%s", drive_name, san_policy_path);
if (RunCommand(cmd, NULL, TRUE) != 0)
uprintf("Command '%s' failed to run");
}
@ -1367,7 +1407,7 @@ void update_progress(const uint64_t processed_bytes)
DWORD WINAPI FormatThread(void* param)
{
int i, r, pt, bt, fs, dt;
BOOL s, ret, use_large_fat32, add_uefi_togo;
BOOL s, ret, use_large_fat32, windows_to_go;
const DWORD SectorSize = SelectedDrive.Geometry.BytesPerSector;
DWORD rSize, wSize, BufSize, DriveIndex = (DWORD)(uintptr_t)param;
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
@ -1377,7 +1417,7 @@ DWORD WINAPI FormatThread(void* param)
FILE* log_fd;
LARGE_INTEGER li;
uint64_t wb;
uint8_t *buffer = NULL, *aligned_buffer;
uint8_t *buffer = NULL, *aligned_buffer, extra_partitions = 0;
char *bb_msg, *guid_volume = NULL;
char drive_name[] = "?:\\";
char drive_letters[27];
@ -1397,7 +1437,14 @@ DWORD WINAPI FormatThread(void* param)
pt = GETPARTTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)));
bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)));
use_large_fat32 = (fs == FS_FAT32) && ((SelectedDrive.DiskSize > LARGE_FAT32_SIZE) || (force_large_fat32));
add_uefi_togo = (fs == FS_NTFS) && (dt == DT_ISO) && (iso_report.has_efi) && (bt == BT_UEFI);
windows_to_go = HAS_TOGO(iso_report) && (Button_GetCheck(GetDlgItem(hMainDialog, IDC_WINDOWS_TO_GO)) == BST_CHECKED);
// Find out if we need to add any extra partitions
if ((windows_to_go) && (bt == BT_UEFI) && (pt == PARTITION_STYLE_GPT))
// According to Microsoft, every GPT disk (we RUN Windows from) must have an MSR due to not having hidden sectors
// http://msdn.microsoft.com/en-us/library/windows/hardware/dn640535.aspx#gpt_faq_what_disk_require_msr
extra_partitions = XP_MSR | XP_EFI;
else if ((fs == FS_NTFS) && (dt == DT_ISO) && (iso_report.has_efi) && ((bt == BT_UEFI) || (windows_to_go)))
extra_partitions = XP_UEFI_TOGO;
PrintInfoDebug(0, MSG_225);
hPhysicalDrive = GetPhysicalHandle(DriveIndex, TRUE, TRUE);
@ -1636,7 +1683,7 @@ DWORD WINAPI FormatThread(void* param)
UpdateProgress(OP_ZERO_MBR, -1.0f);
CHECK_FOR_USER_CANCEL;
if (!CreatePartition(hPhysicalDrive, pt, fs, (pt==PARTITION_STYLE_MBR) && (bt==BT_UEFI), add_uefi_togo)) {
if (!CreatePartition(hPhysicalDrive, pt, fs, (pt==PARTITION_STYLE_MBR) && (bt==BT_UEFI), extra_partitions)) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
goto out;
}
@ -1765,8 +1812,8 @@ DWORD WINAPI FormatThread(void* param)
if (image_path != NULL) {
UpdateProgress(OP_DOS, 0.0f);
PrintInfoDebug(0, MSG_231);
drive_name[2] = 0;
if (HAS_TOGO(iso_report) && (Button_GetCheck(GetDlgItem(hMainDialog, IDC_WINDOWS_TO_GO)) == BST_CHECKED)) {
drive_name[2] = 0; // Ensure our drive is something like 'D:'
if (windows_to_go) {
// Sanity checks
if (fs != FS_NTFS) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_INCOMPATIBLE_FS);
@ -1776,7 +1823,7 @@ DWORD WINAPI FormatThread(void* param)
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
goto out;
}
if (!SetupWinToGo(drive_name)) {
if (!SetupWinToGo(drive_name, (extra_partitions & XP_EFI))) {
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);
goto out;

View File

@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 2.0.0.578"
CAPTION "Rufus 2.0.0.579"
FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -157,7 +157,7 @@ END
IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 2.0.0.578"
CAPTION "Rufus 2.0.0.579"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -283,7 +283,7 @@ END
IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 2.0.0.578"
CAPTION "Rufus 2.0.0.579"
FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -415,7 +415,7 @@ END
IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 2.0.0.578"
CAPTION "Rufus 2.0.0.579"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -671,8 +671,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,578
PRODUCTVERSION 2,0,0,578
FILEVERSION 2,0,0,579
PRODUCTVERSION 2,0,0,579
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -689,13 +689,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "2.0.0.578"
VALUE "FileVersion", "2.0.0.579"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2015 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "2.0.0.578"
VALUE "ProductVersion", "2.0.0.579"
END
END
BLOCK "VarFileInfo"

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Standard User I/O Routines (logging, status, etc.)
* Copyright © 2011-2013 Pete Batard <pete@akeo.ie>
* Copyright © 2011-2015 Pete Batard <pete@akeo.ie>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -181,7 +181,7 @@ char* SizeToHumanReadable(uint64_t size, BOOL log, BOOL fake_units)
} else if (fake_units) {
if (hr_size < 8) {
static_sprintf(str_size, (fabs((hr_size*10.0)-(floor(hr_size + 0.5)*10.0)) < 0.5)?"%0.0f%s":"%0.1f%s",
hr_size, _msg_table[MSG_020+suffix-MSG_000]);
hr_size, _msg_table[MSG_020+suffix-MSG_000]);
} else {
t = (double)upo2((uint16_t)hr_size);
i_size = (uint16_t)((fabs(1.0f-(hr_size / t)) < 0.05f)?t:hr_size);