From 4b76cb2555499ddf1ff201a760f4fc02e6a570ba Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 20 Jan 2015 21:50:24 +0000 Subject: [PATCH] [togo] Add Windows To Go support - part 4 * Ignore partitions we don't care about * Fix issues with AltMountVolume() * Try to support 4k drives when setting up MS EFI partition * Zero the start of the MSR partition to prevent leftover detection * Fix unwanted use of MBR hidden sectors and redundant CloseHandle() * Fix addon of BIOS compatibility extra partition * Print apply image progress to info box --- res/localization/rufus.loc | 7 +++- src/drive.c | 81 ++++++++++++++++++++++---------------- src/drive.h | 1 + src/format.c | 77 ++++++++++++++++++++---------------- src/rufus.c | 10 ++++- src/rufus.h | 5 ++- src/rufus.rc | 16 ++++---- src/stdfn.c | 15 +++++-- src/vhd.c | 2 +- 9 files changed, 129 insertions(+), 85 deletions(-) diff --git a/res/localization/rufus.loc b/res/localization/rufus.loc index 13264f78..5acaa47c 100644 --- a/res/localization/rufus.loc +++ b/res/localization/rufus.loc @@ -415,8 +415,10 @@ t MSG_195 "Using embedded version of %s file(s)" t MSG_196 "IMPORTANT: THIS DRIVE USES A NONSTANDARD SECTOR SIZE!!\n\n" "Conventional drives use a 512-byte sector size but this drive uses a %d-byte one. " "In many cases, this means that you will NOT be able to boot from this drive.\n" - "Rufus can still try to create a bootable drive, but there is NO WARRANTY that it will work." + "Rufus can try to create a bootable drive, but there is NO WARRANTY that it will work." t MSG_197 "Nonstandard sector size detected" +t MSG_198 "Windows To Go can only be installed on a GPT partitioned drive if it has " + "the FIXED attribute set. The current drive was not detected as FIXED." # Status messages - these messages will appear on the status bar t MSG_201 "Cancelling - Please wait..." @@ -505,6 +507,9 @@ t MSG_263 "Use PROPER size units" t MSG_264 "Deleting directory '%s'" t MSG_265 "VMWare disk detection" t MSG_266 "Dual UEFI/BIOS mode" +t MSG_267 "Applying Windows image: %d%% completed" +t MSG_268 "Applying Windows image..." + ################################################################################ ############################# TRANSLATOR END COPY ############################## ################################################################################ diff --git a/src/drive.c b/src/drive.c index 76de027d..1bb15399 100644 --- a/src/drive.c +++ b/src/drive.c @@ -654,7 +654,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys { // MBR partition types that can be mounted in Windows const uint8_t mbr_mountable[] = { 0x01, 0x04, 0x06, 0x07, 0x0b, 0x0c, 0x0e, 0xef }; - BOOL r, hasRufusExtra = FALSE, ret = FALSE, isUefiTogo; + BOOL r, ret = FALSE, isUefiTogo; HANDLE hPhysical; DWORD size; BYTE geometry[256], layout[4096], part_type; @@ -743,7 +743,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"Yes":"No"); if ((part_type == RUFUS_EXTRA_PARTITION_TYPE) || (isUefiTogo)) // This is a partition Rufus created => we can safely ignore it - hasRufusExtra = TRUE; + --SelectedDrive.nPartitions; if (part_type == 0xee) // Flag a protective MBR for non GPT platforms (XP) SelectedDrive.has_protective_mbr = TRUE; } @@ -765,8 +765,11 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / DiskGeometry->Geometry.BytesPerSector, DriveLayout->PartitionEntry[i].Gpt.Attributes); - if (strcmp(tmp, "UEFI:TOGO") == 0) - hasRufusExtra = TRUE; + // Don't register the partitions that we don't care about destroying + if ( (strcmp(tmp, "UEFI:TOGO") == 0) || + (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_MSFT_RESERVED_GUID)) || + (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_SYSTEM_GUID)) ) + --SelectedDrive.nPartitions; if ( (memcmp(&PARTITION_BASIC_DATA_GUID, &DriveLayout->PartitionEntry[i].Gpt.PartitionType, sizeof(GUID)) == 0) && (nWindowsVersion >= WINDOWS_VISTA) ) ret = TRUE; @@ -782,8 +785,6 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys #endif safe_closehandle(hPhysical); - if (hasRufusExtra) - SelectedDrive.nPartitions--; return ret; } @@ -893,8 +894,8 @@ char* AltMountVolume(const char* drive_name, uint8_t part_nr) 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()); + if (!QueryDosDeviceA(drive_name, target[0], MAX_PATH) || (strlen(target[0]) == 0)) { + uprintf("Could not get the DOS volume name for '%s': %s", drive_name, WindowsErrorString()); goto out; } @@ -932,8 +933,8 @@ char* AltMountVolume(const char* drive_name, uint8_t 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()); + if (!QueryDosDeviceA(p, target[0], MAX_PATH) || (strlen(target[0]) == 0)) { + uprintf("Could not find the DOS volume name for partition '%s': %s", p, WindowsErrorString()); goto out; } @@ -955,6 +956,8 @@ out: */ BOOL AltUnmountVolume(const char* drive_name) { + if (drive_name == NULL) + return FALSE; if (!DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_NO_BROADCAST_SYSTEM, drive_name, NULL)) { uprintf("Could not unmount '%s': %s", drive_name, WindowsErrorString()); return FALSE; @@ -1017,7 +1020,8 @@ 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 main_part_size_in_sectors, extra_part_size_in_tracks = 0; + LONGLONG main_part_size_in_sectors, extra_part_size_in_tracks = 0, ms_efi_size; + const LONGLONG bytes_per_track = SelectedDrive.Geometry.SectorsPerTrack * SelectedDrive.Geometry.BytesPerSector; PrintInfoDebug(0, MSG_238, PartitionTypeName[partition_style]); @@ -1030,8 +1034,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = 1024*1024; } else { // Align on Cylinder - DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = - SelectedDrive.Geometry.BytesPerSector * SelectedDrive.Geometry.SectorsPerTrack; + DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = bytes_per_track; } // If required, set the MSR partition (GPT only - must be created before the data part) @@ -1044,24 +1047,42 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m pn++; DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart + DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart; + + // We must zero the beginning of this partition, else we get FAT leftovers and stuff + if (SetFilePointerEx(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, NULL, FILE_BEGIN)) { + bufsize = 65536; // 64K should be enough for everyone + buffer = calloc(bufsize, 1); + if (buffer != NULL) { + if ((!WriteFile(hDrive, buffer, bufsize, &size, NULL)) || (size != bufsize)) + uprintf(" Could not zero MSR: %s", WindowsErrorString()); + free(buffer); + } + } } // Set our main data partition 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 + // Adjust the size according to extra partitions (which we always align to a track) 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 { + uprintf("Adding extra partition"); + if (extra_partitions & XP_EFI) { + // The size of the EFI partition depends on the minimum size we're able to format in FAT32, + // which in turn depends on the cluster size used, which in turn depends on the disk sector size. + if (SelectedDrive.Geometry.BytesPerSector <= 1024) + ms_efi_size = 100*1024*1024; + else if (SelectedDrive.Geometry.BytesPerSector <= 4096) + ms_efi_size = 300*1024*1024; + else + ms_efi_size = 1200*1024*1024; // That'll teach you to have a nonstandard disk! + extra_part_size_in_tracks = (ms_efi_size + bytes_per_track - 1) / bytes_per_track; + } else if (extra_partitions & XP_UEFI_TOGO) + extra_part_size_in_tracks = (MIN_EXTRA_PART_SIZE + bytes_per_track - 1) / bytes_per_track; + else if (extra_partitions & XP_COMPAT) extra_part_size_in_tracks = 1; // One track for the extra partition - } - 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)); + uprintf("Reserved %lld tracks (%s) for extra partition", extra_part_size_in_tracks, + SizeToHumanReadable(extra_part_size_in_tracks * bytes_per_track, 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) @@ -1070,7 +1091,6 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m 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; switch (file_system) { case FS_FAT16: DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x0e; // FAT16 LBA @@ -1108,7 +1128,9 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, (extra_partitions & XP_UEFI_TOGO)?L"UEFI:TOGO":L"EFI system partition"); } else { DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = (extra_partitions & XP_UEFI_TOGO)?0x01:RUFUS_EXTRA_PARTITION_TYPE; - DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack; + if (extra_partitions & XP_COMPAT) + // Set the one track compatibility partition to be all hidden sectors + DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack; } // We need to write the TOGO partition before we refresh the disk @@ -1116,13 +1138,11 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m uprintf("Writing UEFI:TOGO partition..."); if (!SetFilePointerEx(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, NULL, FILE_BEGIN)) { uprintf("Unable to set position"); - safe_closehandle(hDrive); return FALSE; } buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_TOGO), _RT_RCDATA, "uefi-togo.img", &bufsize, FALSE); if (buffer == NULL) { uprintf("Could not access uefi-togo.img"); - safe_closehandle(hDrive); return FALSE; } r = WriteFile(hDrive, buffer, bufsize, &size, NULL); @@ -1131,7 +1151,6 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m uprintf("Write error: %s", WindowsErrorString()); else uprintf("Write error: Wrote %d bytes, expected %d bytes\n", size, bufsize); - safe_closehandle(hDrive); return FALSE; } } @@ -1185,7 +1204,6 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK, (BYTE*)&CreateDisk, size, NULL, 0, &size, NULL ); if (!r) { uprintf("Could not reset disk: %s\n", WindowsErrorString()); - safe_closehandle(hDrive); return FALSE; } @@ -1193,14 +1211,11 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m r = DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, (BYTE*)&DriveLayoutEx, size, NULL, 0, &size, NULL ); if (!r) { uprintf("Could not set drive layout: %s\n", WindowsErrorString()); - safe_closehandle(hDrive); return FALSE; } - if (!RefreshDriveLayout(hDrive)) { - safe_closehandle(hDrive); + if (!RefreshDriveLayout(hDrive)) return FALSE; - } return TRUE; } diff --git a/src/drive.h b/src/drive.h index 133b54bd..605ad413 100644 --- a/src/drive.h +++ b/src/drive.h @@ -33,6 +33,7 @@ #define XP_MSR 0x01 #define XP_EFI 0x02 #define XP_UEFI_TOGO 0x04 +#define XP_COMPAT 0x08 /* We need a redef of these MS structure */ typedef struct { diff --git a/src/format.c b/src/format.c index e2fa0eca..0233f66b 100644 --- a/src/format.c +++ b/src/format.c @@ -1229,21 +1229,26 @@ out: 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, *ms_efi, image[128], cmd[128]; + char *mounted_iso, *ms_efi = NULL, image[128], cmd[128]; wchar_t wVolumeName[] = L"?:"; unsigned char *buffer; DWORD bufsize; + ULONG cluster_size; 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"); + // Additional sanity checks + if ( ((use_ms_efi) && (SelectedDrive.Geometry.MediaType != FixedMedia)) || + ((nWindowsVersion < WINDOWS_8) || ((WimExtractCheck() & 4) == 0)) ) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED; return FALSE; } + if (ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)) != FS_NTFS) { + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_INCOMPATIBLE_FS); + return FALSE; + } // First, we need to access the install.wim image, that resides on the ISO mounted_iso = MountISO(image_path); @@ -1274,13 +1279,23 @@ BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_ASSIGN_LETTER); return FALSE; } - fs_index = 0; + uprintf("Formatting EFI system partition %s", ms_efi); + // According to Ubuntu (https://bugs.launchpad.net/ubuntu/+source/partman-efi/+bug/811485) you want to use FAT32. + // However, you have to be careful that the cluster size needs to be greater or equal to the sector size, which + // in turn has an impact on the minimum EFI partition size we can create (see ms_efi_size_MB in drive.c) + if (SelectedDrive.Geometry.BytesPerSector <= 1024) + cluster_size = 1024; + else if (SelectedDrive.Geometry.BytesPerSector <= 4096) + cluster_size = 4096; + else // Go for broke + cluster_size = (ULONG)SelectedDrive.Geometry.BytesPerSector; + fs_index = 1; // FAT32 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); + + // Boy do you *NOT* want to specify a label here, and spend HOURS figuring out why your EFI partition cannot boot... + // TODO: Can we avoid resetting the progress bar here? + pfFormatEx(wVolumeName, SelectedDrive.Geometry.MediaType, L"FAT32", L"", TRUE, cluster_size, FormatExCallback); if (IS_ERROR(FormatStatus)) { uprintf("Failed to format EFI partition"); AltUnmountVolume(ms_efi); @@ -1445,6 +1460,8 @@ DWORD WINAPI FormatThread(void* param) 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; + else if (IsChecked(IDC_EXTRA_PARTITION)) + extra_partitions = XP_COMPAT; PrintInfoDebug(0, MSG_225); hPhysicalDrive = GetPhysicalHandle(DriveIndex, TRUE, TRUE); @@ -1808,27 +1825,19 @@ DWORD WINAPI FormatThread(void* param) IGNORE_RETVAL(_chdirU(app_dir)); if (!CopyFileU(FILES_DIR "\\grub4dos\\grldr", grub4dos_dst, FALSE)) uprintf("Failed to copy file: %s", WindowsErrorString()); - } else if (dt == DT_ISO) { - if (image_path != NULL) { - UpdateProgress(OP_DOS, 0.0f); + } else if ((dt == DT_ISO) && (image_path != NULL)) { + UpdateProgress(OP_DOS, 0.0f); + drive_name[2] = 0; // Ensure our drive is something like 'D:' + if (windows_to_go) { + PrintInfoDebug(0, MSG_268); + 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; + } + } else { PrintInfoDebug(0, MSG_231); - 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); - goto out; - } - if ((nWindowsVersion < WINDOWS_8) || ((WimExtractCheck() & 4) == 0)) { - FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED; - goto out; - } - 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; - } - } else if (!ExtractISO(image_path, drive_name, FALSE)) { + if (!ExtractISO(image_path, drive_name, FALSE)) { if (!IS_ERROR(FormatStatus)) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT); goto out; @@ -1858,11 +1867,11 @@ DWORD WINAPI FormatThread(void* param) } } } - } - if ( (bt == BT_BIOS) && (IS_WINPE(iso_report.winpe)) ) { - // Apply WinPe fixup - if (!SetupWinPE(drive_name[0])) - FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); + if ( (bt == BT_BIOS) && (IS_WINPE(iso_report.winpe)) ) { + // Apply WinPe fixup + if (!SetupWinPE(drive_name[0])) + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); + } } } UpdateProgress(OP_FINALIZE, -1.0f); diff --git a/src/rufus.c b/src/rufus.c index 96ad85d5..a3b7749c 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -919,7 +919,6 @@ static void DisplayISOProps(void) uprintf(" Has Symlinks: %s", YesNo(iso_report.has_symlinks)); uprintf(" Has a >4GB file: %s", YesNo(iso_report.has_4GB_file)); uprintf(" Uses Bootmgr: %s", YesNo(iso_report.has_bootmgr)); - // TODO: report x86, x64, Arm, Itanic? uprintf(" Uses EFI: %s%s", YesNo(iso_report.has_efi), IS_WIN7_EFI(iso_report) ? " (win7_x64)" : ""); uprintf(" Uses Grub 2: %s", YesNo(iso_report.has_grub2)); uprintf(" Uses Grub4DOS: %s", YesNo(iso_report.has_grub4dos)); @@ -1156,7 +1155,7 @@ static void ToggleToGo(void) static BOOL BootCheck(void) { - int i, fs, bt, dt, r; + int i, fs, bt, dt, pt, r; FILE *fd; DWORD len; BOOL in_files_dir = FALSE; @@ -1170,6 +1169,7 @@ static BOOL BootCheck(void) syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0; safe_free(grub2_buf); dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); + pt = GETPARTTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); if ((dt == DT_ISO) || (dt == DT_IMG)) { if (image_path == NULL) { // Please click on the disc button to select a bootable ISO @@ -1195,6 +1195,12 @@ static BOOL BootCheck(void) MessageBoxU(hMainDialog, lmprintf(MSG_097), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL); return FALSE; } else if (SelectedDrive.Geometry.MediaType != FixedMedia) { + if ((bt == BT_UEFI) && (pt == PARTITION_STYLE_GPT)) { + // We're screwed since we need access to 2 partitions at the same time to set this, which + // Windows can't do. Cue in Arthur's Theme: "♫ I know it's stupid... but it's true. ♫" + MessageBoxU(hMainDialog, lmprintf(MSG_198), lmprintf(MSG_190), MB_OK|MB_ICONERROR|MB_IS_RTL); + return FALSE; + } // I never had any success with drives that have the REMOVABLE attribute set, no matter the // method or tool I tried. If you manage to get this working, I'd like to hear from you! if (MessageBoxU(hMainDialog, lmprintf(MSG_098), lmprintf(MSG_190), MB_YESNO|MB_ICONWARNING|MB_IS_RTL) != IDYES) diff --git a/src/rufus.h b/src/rufus.h index c771c992..e4243dcc 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -42,7 +42,7 @@ #define DRIVE_ACCESS_RETRIES 60 // How many times we should retry #define DRIVE_INDEX_MIN 0x00000080 #define DRIVE_INDEX_MAX 0x000000C0 -#define MIN_EXTRA_PART_SIZE 2048 // Minimum size of the extra partition, in sectors +#define MIN_EXTRA_PART_SIZE (1024*1024) // Minimum size of the extra partition, in bytes #define MAX_DRIVES (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN) #define MAX_TOOLTIPS 128 #define MAX_SIZE_SUFFIXES 6 // bytes, KB, MB, GB, TB, PB @@ -210,7 +210,7 @@ typedef struct { DWORD FirstSector; char proposed_label[16]; int PartitionType; - int nPartitions; + int nPartitions; // number of partitions we actually care about int FSType; BOOL has_protective_mbr; BOOL has_mbr_uefi_marker; @@ -396,6 +396,7 @@ extern BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size); extern unsigned char* GetResource(HMODULE module, char* name, char* type, const char* desc, DWORD* len, BOOL duplicate); extern DWORD GetResourceSize(HMODULE module, char* name, char* type, const char* desc); extern DWORD RunCommand(const char* cmdline, const char* dir, BOOL log); +extern BOOL CompareGUID(const GUID *guid1, const GUID *guid2); extern BOOL GetUSBDevices(DWORD devnum); extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue); extern LONG GetEntryWidth(HWND hDropDown, const char* entry); diff --git a/src/rufus.rc b/src/rufus.rc index 7f8f1b06..d164a38e 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -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.579" +CAPTION "Rufus 2.0.0.580" 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.579" +CAPTION "Rufus 2.0.0.580" 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.579" +CAPTION "Rufus 2.0.0.580" 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.579" +CAPTION "Rufus 2.0.0.580" 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,579 - PRODUCTVERSION 2,0,0,579 + FILEVERSION 2,0,0,580 + PRODUCTVERSION 2,0,0,580 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.579" + VALUE "FileVersion", "2.0.0.580" 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.579" + VALUE "ProductVersion", "2.0.0.580" END END BLOCK "VarFileInfo" diff --git a/src/stdfn.c b/src/stdfn.c index 8e877d22..b516886e 100644 --- a/src/stdfn.c +++ b/src/stdfn.c @@ -590,13 +590,20 @@ out: return ret; } +BOOL CompareGUID(const GUID *guid1, const GUID *guid2) { + if ((guid1 != NULL) && (guid2 != NULL)) { + return (memcmp(guid1, guid2, sizeof(GUID)) == 0); + } + return FALSE; +} + /* * Set or restore a Local Group Policy DWORD key indexed by szPath/SzPolicy */ #pragma push_macro("INTERFACE") #undef INTERFACE #define INTERFACE IGroupPolicyObject -#define REGISTRY_EXTENSION_GUID { 0x35378EAC, 0x683F, 0x11D2, {0xA8, 0x9A, 0x00, 0xC0, 0x4F, 0xBB, 0xCF, 0xA2} } +#define REGISTRY_EXTENSION_GUID { 0x35378EACL, 0x683F, 0x11D2, {0xA8, 0x9A, 0x00, 0xC0, 0x4F, 0xBB, 0xCF, 0xA2} } #define GPO_OPEN_LOAD_REGISTRY 1 #define GPO_SECTION_MACHINE 2 typedef enum _GROUP_POLICY_OBJECT_TYPE { @@ -650,12 +657,12 @@ DWORD WINAPI SetLGPThread(LPVOID param) HKEY path_key = NULL, policy_key = NULL; // MSVC is finicky about these ones => redefine them const IID my_IID_IGroupPolicyObject = - { 0xea502723, 0xa23d, 0x11d1, { 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } }; + { 0xea502723L, 0xa23d, 0x11d1, { 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } }; const IID my_CLSID_GroupPolicyObject = - { 0xea502722, 0xa23d, 0x11d1, { 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } }; + { 0xea502722L, 0xa23d, 0x11d1, { 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } }; GUID ext_guid = REGISTRY_EXTENSION_GUID; // Can be anything really - GUID snap_guid = { 0x3D271CFC, 0x2BC6, 0x4AC2, {0xB6, 0x33, 0x3B, 0xDF, 0xF5, 0xBD, 0xAB, 0x2A} }; + GUID snap_guid = { 0x3D271CFCL, 0x2BC6, 0x4AC2, {0xB6, 0x33, 0x3B, 0xDF, 0xF5, 0xBD, 0xAB, 0x2A} }; // Reinitialize COM since it's not shared between threads IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); diff --git a/src/vhd.c b/src/vhd.c index 2f2cb2a6..96c6ece7 100644 --- a/src/vhd.c +++ b/src/vhd.c @@ -509,7 +509,7 @@ DWORD WINAPI WimProgressCallback(DWORD dwMsgId, WPARAM wParam, LPARAM lParam, PV switch (dwMsgId) { case WIM_MSG_PROGRESS: - uprintf(" %d%% completed", (DWORD)wParam); + PrintInfo(0, MSG_267, (DWORD)wParam); UpdateProgress(OP_DOS, 0.98f*(DWORD)wParam); break; case WIM_MSG_PROCESS: