[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
This commit is contained in:
Pete Batard 2015-01-20 21:50:24 +00:00
parent ed9fae7c81
commit 4b76cb2555
9 changed files with 129 additions and 85 deletions

View file

@ -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" 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. " "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" "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_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 # Status messages - these messages will appear on the status bar
t MSG_201 "Cancelling - Please wait..." 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_264 "Deleting directory '%s'"
t MSG_265 "VMWare disk detection" t MSG_265 "VMWare disk detection"
t MSG_266 "Dual UEFI/BIOS mode" t MSG_266 "Dual UEFI/BIOS mode"
t MSG_267 "Applying Windows image: %d%% completed"
t MSG_268 "Applying Windows image..."
################################################################################ ################################################################################
############################# TRANSLATOR END COPY ############################## ############################# TRANSLATOR END COPY ##############################
################################################################################ ################################################################################

View file

@ -654,7 +654,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
{ {
// MBR partition types that can be mounted in Windows // MBR partition types that can be mounted in Windows
const uint8_t mbr_mountable[] = { 0x01, 0x04, 0x06, 0x07, 0x0b, 0x0c, 0x0e, 0xef }; 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; HANDLE hPhysical;
DWORD size; DWORD size;
BYTE geometry[256], layout[4096], part_type; 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"); DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"Yes":"No");
if ((part_type == RUFUS_EXTRA_PARTITION_TYPE) || (isUefiTogo)) if ((part_type == RUFUS_EXTRA_PARTITION_TYPE) || (isUefiTogo))
// This is a partition Rufus created => we can safely ignore it // 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) if (part_type == 0xee) // Flag a protective MBR for non GPT platforms (XP)
SelectedDrive.has_protective_mbr = TRUE; 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), 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].PartitionLength, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / DiskGeometry->Geometry.BytesPerSector,
DriveLayout->PartitionEntry[i].Gpt.Attributes); DriveLayout->PartitionEntry[i].Gpt.Attributes);
if (strcmp(tmp, "UEFI:TOGO") == 0) // Don't register the partitions that we don't care about destroying
hasRufusExtra = TRUE; 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) && if ( (memcmp(&PARTITION_BASIC_DATA_GUID, &DriveLayout->PartitionEntry[i].Gpt.PartitionType, sizeof(GUID)) == 0) &&
(nWindowsVersion >= WINDOWS_VISTA) ) (nWindowsVersion >= WINDOWS_VISTA) )
ret = TRUE; ret = TRUE;
@ -782,8 +785,6 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
#endif #endif
safe_closehandle(hPhysical); safe_closehandle(hPhysical);
if (hasRufusExtra)
SelectedDrive.nPartitions--;
return ret; return ret;
} }
@ -893,8 +894,8 @@ char* AltMountVolume(const char* drive_name, uint8_t part_nr)
target[0][0] = 0; target[0][0] = 0;
// Convert our drive letter to something like "\Device\HarddiskVolume9" // Convert our drive letter to something like "\Device\HarddiskVolume9"
if (!QueryDosDeviceA(drive_name, target[0], MAX_PATH) && (strlen(target[0]) == 0)) { 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()); uprintf("Could not get the DOS volume name for '%s': %s", drive_name, WindowsErrorString());
goto out; goto out;
} }
@ -932,8 +933,8 @@ char* AltMountVolume(const char* drive_name, uint8_t part_nr)
p[++i] = 0; p[++i] = 0;
target[0][0] = 0; target[0][0] = 0;
if (!QueryDosDeviceA(p, target[0], MAX_PATH) && (strlen(target[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()); uprintf("Could not find the DOS volume name for partition '%s': %s", p, WindowsErrorString());
goto out; goto out;
} }
@ -955,6 +956,8 @@ out:
*/ */
BOOL AltUnmountVolume(const char* drive_name) BOOL AltUnmountVolume(const char* drive_name)
{ {
if (drive_name == NULL)
return FALSE;
if (!DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_NO_BROADCAST_SYSTEM, drive_name, NULL)) { if (!DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_NO_BROADCAST_SYSTEM, drive_name, NULL)) {
uprintf("Could not unmount '%s': %s", drive_name, WindowsErrorString()); uprintf("Could not unmount '%s': %s", drive_name, WindowsErrorString());
return FALSE; return FALSE;
@ -1017,7 +1020,8 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0}; DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0};
BOOL r; BOOL r;
DWORD i, size, bufsize, pn = 0; 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]); 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; DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = 1024*1024;
} else { } else {
// Align on Cylinder // Align on Cylinder
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = bytes_per_track;
SelectedDrive.Geometry.BytesPerSector * SelectedDrive.Geometry.SectorsPerTrack;
} }
// If required, set the MSR partition (GPT only - must be created before the data part) // 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++; pn++;
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart + DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.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 // Set our main data partition
main_part_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 // Need 33 sectors at the end for secondary GPT
SelectedDrive.Geometry.BytesPerSector - ((partition_style == PARTITION_STYLE_GPT)?33:0); 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) {
if (extra_partitions & (XP_UEFI_TOGO | XP_EFI)) { uprintf("Adding extra partition");
// TODO: this will explode to 800MB instead of 100MB on 4K sectors... if (extra_partitions & XP_EFI) {
extra_part_size_in_tracks = ((MIN_EXTRA_PART_SIZE*((extra_partitions & XP_EFI)?100:1)) // The size of the EFI partition depends on the minimum size we're able to format in FAT32,
+ SelectedDrive.Geometry.SectorsPerTrack - 1) / SelectedDrive.Geometry.SectorsPerTrack; // which in turn depends on the cluster size used, which in turn depends on the disk sector size.
} else { 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 extra_part_size_in_tracks = 1; // One track for the extra partition
} uprintf("Reserved %lld tracks (%s) for extra partition", extra_part_size_in_tracks,
uprintf("Reserving %lld tracks (%s) for extra partition", extra_part_size_in_tracks, SizeToHumanReadable(extra_part_size_in_tracks * bytes_per_track, TRUE, FALSE));
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) - main_part_size_in_sectors = ((main_part_size_in_sectors / SelectedDrive.Geometry.SectorsPerTrack) -
extra_part_size_in_tracks) * SelectedDrive.Geometry.SectorsPerTrack; extra_part_size_in_tracks) * SelectedDrive.Geometry.SectorsPerTrack;
if (main_part_size_in_sectors <= 0) 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; DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = main_part_size_in_sectors * SelectedDrive.Geometry.BytesPerSector;
if (partition_style == PARTITION_STYLE_MBR) { if (partition_style == PARTITION_STYLE_MBR) {
DriveLayoutEx.PartitionEntry[pn].Mbr.BootIndicator = IsChecked(IDC_BOOT); DriveLayoutEx.PartitionEntry[pn].Mbr.BootIndicator = IsChecked(IDC_BOOT);
DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack;
switch (file_system) { switch (file_system) {
case FS_FAT16: case FS_FAT16:
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x0e; // FAT16 LBA 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"); wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, (extra_partitions & XP_UEFI_TOGO)?L"UEFI:TOGO":L"EFI system partition");
} else { } else {
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = (extra_partitions & XP_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; 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 // 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..."); uprintf("Writing UEFI:TOGO partition...");
if (!SetFilePointerEx(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, NULL, FILE_BEGIN)) { if (!SetFilePointerEx(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, NULL, FILE_BEGIN)) {
uprintf("Unable to set position"); uprintf("Unable to set position");
safe_closehandle(hDrive);
return FALSE; return FALSE;
} }
buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_TOGO), _RT_RCDATA, "uefi-togo.img", &bufsize, FALSE); buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_TOGO), _RT_RCDATA, "uefi-togo.img", &bufsize, FALSE);
if (buffer == NULL) { if (buffer == NULL) {
uprintf("Could not access uefi-togo.img"); uprintf("Could not access uefi-togo.img");
safe_closehandle(hDrive);
return FALSE; return FALSE;
} }
r = WriteFile(hDrive, buffer, bufsize, &size, NULL); 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()); uprintf("Write error: %s", WindowsErrorString());
else else
uprintf("Write error: Wrote %d bytes, expected %d bytes\n", size, bufsize); uprintf("Write error: Wrote %d bytes, expected %d bytes\n", size, bufsize);
safe_closehandle(hDrive);
return FALSE; 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 ); r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK, (BYTE*)&CreateDisk, size, NULL, 0, &size, NULL );
if (!r) { if (!r) {
uprintf("Could not reset disk: %s\n", WindowsErrorString()); uprintf("Could not reset disk: %s\n", WindowsErrorString());
safe_closehandle(hDrive);
return FALSE; 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 ); r = DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, (BYTE*)&DriveLayoutEx, size, NULL, 0, &size, NULL );
if (!r) { if (!r) {
uprintf("Could not set drive layout: %s\n", WindowsErrorString()); uprintf("Could not set drive layout: %s\n", WindowsErrorString());
safe_closehandle(hDrive);
return FALSE; return FALSE;
} }
if (!RefreshDriveLayout(hDrive)) { if (!RefreshDriveLayout(hDrive))
safe_closehandle(hDrive);
return FALSE; return FALSE;
}
return TRUE; return TRUE;
} }

View file

@ -33,6 +33,7 @@
#define XP_MSR 0x01 #define XP_MSR 0x01
#define XP_EFI 0x02 #define XP_EFI 0x02
#define XP_UEFI_TOGO 0x04 #define XP_UEFI_TOGO 0x04
#define XP_COMPAT 0x08
/* We need a redef of these MS structure */ /* We need a redef of these MS structure */
typedef struct { typedef struct {

View file

@ -1229,21 +1229,26 @@ out:
BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi) 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 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"?:"; wchar_t wVolumeName[] = L"?:";
unsigned char *buffer; unsigned char *buffer;
DWORD bufsize; DWORD bufsize;
ULONG cluster_size;
FILE* fd; FILE* fd;
PF_DECL(FormatEx); PF_DECL(FormatEx);
PF_INIT(FormatEx, Fmifs); PF_INIT(FormatEx, Fmifs);
uprintf("Windows To Go mode selected"); uprintf("Windows To Go mode selected");
if ((use_ms_efi) && (SelectedDrive.Geometry.MediaType != FixedMedia)) { // Additional sanity checks
// Arthur's Theme: "♫ I know it's stupid... but it's true. ♫" if ( ((use_ms_efi) && (SelectedDrive.Geometry.MediaType != FixedMedia)) ||
uprintf("Cannot set 'Windows To Go' for a GPT target unless it is a fixed drive"); ((nWindowsVersion < WINDOWS_8) || ((WimExtractCheck() & 4) == 0)) ) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED; FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
return FALSE; 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 // First, we need to access the install.wim image, that resides on the ISO
mounted_iso = MountISO(image_path); 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); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_ASSIGN_LETTER);
return FALSE; 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; task_number = 0;
wVolumeName[0] = ms_efi[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... // 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"", // TODO: Can we avoid resetting the progress bar here?
TRUE, 1024, FormatExCallback); pfFormatEx(wVolumeName, SelectedDrive.Geometry.MediaType, L"FAT32", L"", TRUE, cluster_size, FormatExCallback);
if (IS_ERROR(FormatStatus)) { if (IS_ERROR(FormatStatus)) {
uprintf("Failed to format EFI partition"); uprintf("Failed to format EFI partition");
AltUnmountVolume(ms_efi); AltUnmountVolume(ms_efi);
@ -1445,6 +1460,8 @@ DWORD WINAPI FormatThread(void* param)
extra_partitions = XP_MSR | XP_EFI; extra_partitions = XP_MSR | XP_EFI;
else if ((fs == FS_NTFS) && (dt == DT_ISO) && (iso_report.has_efi) && ((bt == BT_UEFI) || (windows_to_go))) else if ((fs == FS_NTFS) && (dt == DT_ISO) && (iso_report.has_efi) && ((bt == BT_UEFI) || (windows_to_go)))
extra_partitions = XP_UEFI_TOGO; extra_partitions = XP_UEFI_TOGO;
else if (IsChecked(IDC_EXTRA_PARTITION))
extra_partitions = XP_COMPAT;
PrintInfoDebug(0, MSG_225); PrintInfoDebug(0, MSG_225);
hPhysicalDrive = GetPhysicalHandle(DriveIndex, TRUE, TRUE); hPhysicalDrive = GetPhysicalHandle(DriveIndex, TRUE, TRUE);
@ -1808,27 +1825,19 @@ DWORD WINAPI FormatThread(void* param)
IGNORE_RETVAL(_chdirU(app_dir)); IGNORE_RETVAL(_chdirU(app_dir));
if (!CopyFileU(FILES_DIR "\\grub4dos\\grldr", grub4dos_dst, FALSE)) if (!CopyFileU(FILES_DIR "\\grub4dos\\grldr", grub4dos_dst, FALSE))
uprintf("Failed to copy file: %s", WindowsErrorString()); uprintf("Failed to copy file: %s", WindowsErrorString());
} else if (dt == DT_ISO) { } else if ((dt == DT_ISO) && (image_path != NULL)) {
if (image_path != NULL) { UpdateProgress(OP_DOS, 0.0f);
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); PrintInfoDebug(0, MSG_231);
drive_name[2] = 0; // Ensure our drive is something like 'D:' if (!ExtractISO(image_path, drive_name, FALSE)) {
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 (!IS_ERROR(FormatStatus)) if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);
goto out; goto out;
@ -1858,11 +1867,11 @@ DWORD WINAPI FormatThread(void* param)
} }
} }
} }
} if ( (bt == BT_BIOS) && (IS_WINPE(iso_report.winpe)) ) {
if ( (bt == BT_BIOS) && (IS_WINPE(iso_report.winpe)) ) { // Apply WinPe fixup
// Apply WinPe fixup if (!SetupWinPE(drive_name[0]))
if (!SetupWinPE(drive_name[0])) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH);
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_PATCH); }
} }
} }
UpdateProgress(OP_FINALIZE, -1.0f); UpdateProgress(OP_FINALIZE, -1.0f);

View file

@ -919,7 +919,6 @@ static void DisplayISOProps(void)
uprintf(" Has Symlinks: %s", YesNo(iso_report.has_symlinks)); uprintf(" Has Symlinks: %s", YesNo(iso_report.has_symlinks));
uprintf(" Has a >4GB file: %s", YesNo(iso_report.has_4GB_file)); uprintf(" Has a >4GB file: %s", YesNo(iso_report.has_4GB_file));
uprintf(" Uses Bootmgr: %s", YesNo(iso_report.has_bootmgr)); 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 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 Grub 2: %s", YesNo(iso_report.has_grub2));
uprintf(" Uses Grub4DOS: %s", YesNo(iso_report.has_grub4dos)); uprintf(" Uses Grub4DOS: %s", YesNo(iso_report.has_grub4dos));
@ -1156,7 +1155,7 @@ static void ToggleToGo(void)
static BOOL BootCheck(void) static BOOL BootCheck(void)
{ {
int i, fs, bt, dt, r; int i, fs, bt, dt, pt, r;
FILE *fd; FILE *fd;
DWORD len; DWORD len;
BOOL in_files_dir = FALSE; BOOL in_files_dir = FALSE;
@ -1170,6 +1169,7 @@ static BOOL BootCheck(void)
syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0; syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0;
safe_free(grub2_buf); safe_free(grub2_buf);
dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); 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 ((dt == DT_ISO) || (dt == DT_IMG)) {
if (image_path == NULL) { if (image_path == NULL) {
// Please click on the disc button to select a bootable ISO // 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); MessageBoxU(hMainDialog, lmprintf(MSG_097), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL);
return FALSE; return FALSE;
} else if (SelectedDrive.Geometry.MediaType != FixedMedia) { } 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 // 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! // 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) if (MessageBoxU(hMainDialog, lmprintf(MSG_098), lmprintf(MSG_190), MB_YESNO|MB_ICONWARNING|MB_IS_RTL) != IDYES)

View file

@ -42,7 +42,7 @@
#define DRIVE_ACCESS_RETRIES 60 // How many times we should retry #define DRIVE_ACCESS_RETRIES 60 // How many times we should retry
#define DRIVE_INDEX_MIN 0x00000080 #define DRIVE_INDEX_MIN 0x00000080
#define DRIVE_INDEX_MAX 0x000000C0 #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_DRIVES (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN)
#define MAX_TOOLTIPS 128 #define MAX_TOOLTIPS 128
#define MAX_SIZE_SUFFIXES 6 // bytes, KB, MB, GB, TB, PB #define MAX_SIZE_SUFFIXES 6 // bytes, KB, MB, GB, TB, PB
@ -210,7 +210,7 @@ typedef struct {
DWORD FirstSector; DWORD FirstSector;
char proposed_label[16]; char proposed_label[16];
int PartitionType; int PartitionType;
int nPartitions; int nPartitions; // number of partitions we actually care about
int FSType; int FSType;
BOOL has_protective_mbr; BOOL has_protective_mbr;
BOOL has_mbr_uefi_marker; 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 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 GetResourceSize(HMODULE module, char* name, char* type, const char* desc);
extern DWORD RunCommand(const char* cmdline, const char* dir, BOOL log); 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 GetUSBDevices(DWORD devnum);
extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue); extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue);
extern LONG GetEntryWidth(HWND hDropDown, const char* entry); extern LONG GetEntryWidth(HWND hDropDown, const char* entry);

View file

@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 242, 376 IDD_DIALOG DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU 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 FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -157,7 +157,7 @@ END
IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376 IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU 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 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -283,7 +283,7 @@ END
IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376 IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU 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 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 FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -415,7 +415,7 @@ END
IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376 IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU 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 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 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -671,8 +671,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,579 FILEVERSION 2,0,0,580
PRODUCTVERSION 2,0,0,579 PRODUCTVERSION 2,0,0,580
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -689,13 +689,13 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "2.0.0.579" VALUE "FileVersion", "2.0.0.580"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2015 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2015 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", "2.0.0.579" VALUE "ProductVersion", "2.0.0.580"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -590,13 +590,20 @@ out:
return ret; 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 * Set or restore a Local Group Policy DWORD key indexed by szPath/SzPolicy
*/ */
#pragma push_macro("INTERFACE") #pragma push_macro("INTERFACE")
#undef INTERFACE #undef INTERFACE
#define INTERFACE IGroupPolicyObject #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_OPEN_LOAD_REGISTRY 1
#define GPO_SECTION_MACHINE 2 #define GPO_SECTION_MACHINE 2
typedef enum _GROUP_POLICY_OBJECT_TYPE { typedef enum _GROUP_POLICY_OBJECT_TYPE {
@ -650,12 +657,12 @@ DWORD WINAPI SetLGPThread(LPVOID param)
HKEY path_key = NULL, policy_key = NULL; HKEY path_key = NULL, policy_key = NULL;
// MSVC is finicky about these ones => redefine them // MSVC is finicky about these ones => redefine them
const IID my_IID_IGroupPolicyObject = 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 = 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; GUID ext_guid = REGISTRY_EXTENSION_GUID;
// Can be anything really // 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 // Reinitialize COM since it's not shared between threads
IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));

View file

@ -509,7 +509,7 @@ DWORD WINAPI WimProgressCallback(DWORD dwMsgId, WPARAM wParam, LPARAM lParam, PV
switch (dwMsgId) { switch (dwMsgId) {
case WIM_MSG_PROGRESS: case WIM_MSG_PROGRESS:
uprintf(" %d%% completed", (DWORD)wParam); PrintInfo(0, MSG_267, (DWORD)wParam);
UpdateProgress(OP_DOS, 0.98f*(DWORD)wParam); UpdateProgress(OP_DOS, 0.98f*(DWORD)wParam);
break; break;
case WIM_MSG_PROCESS: case WIM_MSG_PROCESS: