1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2024-08-14 23:57:05 +00:00

[core] partial overhaul of the partitioning and formatting facilities

* Add VDS formatting support (through an Alt-V cheat mode)
* Add partition index support
* Improve(?) Windows To Go support by following Microsoft recommended partition order
* Code refactoring & cleanup
This commit is contained in:
Pete Batard 2019-04-25 18:58:55 +01:00
parent 4b38483a68
commit 1c39a80d72
No known key found for this signature in database
GPG key ID: 38E0CF5E69EDD671
11 changed files with 955 additions and 509 deletions

View file

@ -45,6 +45,11 @@
#include "fat32.h"
#include "ntfs.h"
#define GLOBALROOT_NAME "\\\\?\\GLOBALROOT"
const char* sfd_name = "Super Floppy Disk";
const char* groot_name = GLOBALROOT_NAME;
const size_t groot_len = sizeof(GLOBALROOT_NAME) - 1;
#if !defined(PARTITION_BASIC_DATA_GUID)
const GUID PARTITION_BASIC_DATA_GUID =
{ 0xebd0a0a2L, 0xb9e5, 0x4433, {0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7} };
@ -70,6 +75,8 @@ const IID IID_IVdsSwProvider = { 0x9aa58360, 0xce33, 0x4f92, { 0xb6, 0x58, 0xed,
const IID IID_IVdsPack = { 0x3b69d7f5, 0x9d94, 0x4648, { 0x91, 0xca, 0x79, 0x93, 0x9b, 0xa2, 0x63, 0xbf } };
const IID IID_IVdsDisk = { 0x07e5c822, 0xf00c, 0x47a1, { 0x8f, 0xce, 0xb2, 0x44, 0xda, 0x56, 0xfd, 0x06 } };
const IID IID_IVdsAdvancedDisk = { 0x6e6f6b40, 0x977c, 0x4069, { 0xbd, 0xdd, 0xac, 0x71, 0x00, 0x59, 0xf8, 0xc0 } };
const IID IID_IVdsVolume = { 0x88306BB2, 0xE71F, 0x478C, { 0x86, 0xA2, 0x79, 0xDA, 0x20, 0x0A, 0x0F, 0x11} };
const IID IID_IVdsVolumeMF3 = { 0x6788FAF9, 0x214E, 0x4B85, { 0xBA, 0x59, 0x26, 0x69, 0x53, 0x61, 0x6E, 0x09 } };
#endif
PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryVolumeInformationFile, (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS));
@ -79,8 +86,8 @@ PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryVolumeInformationFile, (HANDLE, PIO_STATUS_
*/
RUFUS_DRIVE_INFO SelectedDrive;
BOOL installed_uefi_ntfs;
DWORD partition_index[3];
uint64_t persistence_size = 0;
const char* sfd_name = "Super Floppy Disk";
/*
* The following methods get or set the AutoMount setting (which is different from AutoRun)
@ -153,7 +160,9 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr
goto out;
// Resolve a device path, so that we can look for that handle in case of access issues.
if (QueryDosDeviceA(&Path[4], DevPath, sizeof(DevPath)) == 0)
if (safe_strncmp(Path, groot_name, groot_len) == 0)
static_strcpy(DevPath, &Path[groot_len]);
else if (QueryDosDeviceA(&Path[4], DevPath, sizeof(DevPath)) == 0)
strcpy(DevPath, "???");
for (i = 0; i < DRIVE_ACCESS_RETRIES; i++) {
@ -237,14 +246,18 @@ out:
* Return the path to access a partition on a specific disk, or NULL on error.
* The string is allocated and must be freed (to ensure concurrent access)
*/
char* GetPartitionName(DWORD DriveIndex, DWORD PartitionNumber)
char* GetPartitionName(DWORD DriveIndex, DWORD PartitionIndex)
{
BOOL success = FALSE;
char partition_name[32];
CheckDriveIndex(DriveIndex);
if (PartitionIndex >= MAX_PARTITIONS)
goto out;
if (PartitionIndex == 0)
PartitionIndex = 1;
static_sprintf(partition_name, "\\Device\\Harddisk%lu\\Partition%lu", DriveIndex, PartitionNumber);
static_sprintf(partition_name, "\\Device\\Harddisk%lu\\Partition%lu", DriveIndex, PartitionIndex);
success = TRUE;
out:
return (success) ? safe_strdup(partition_name) : NULL;
@ -263,25 +276,30 @@ HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, B
}
/*
* Return the first GUID volume name for the associated drive or NULL if not found
* Return the GUID volume name for the disk and partition specified, or NULL if not found.
* See http://msdn.microsoft.com/en-us/library/cc542456.aspx
* The returned string is allocated and must be freed
* PartitionIndex starts at 1 (for the first partition). If PartitionIndex is zero, then
* the first partition found by this function (which *MAY NOT* be the actual first partition)
* is returned. The returned string is allocated and must be freed.
*/
char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent)
char* GetLogicalName(DWORD DriveIndex, DWORD PartitionIndex, BOOL bKeepTrailingBackslash, BOOL bSilent)
{
BOOL success = FALSE;
char volume_name[MAX_PATH];
static const char* ignore_device[] = { "\\Device\\CdRom", "\\Device\\Floppy" };
static const char* volume_start = "\\\\?\\";
char *ret = NULL, volume_name[MAX_PATH], path[MAX_PATH];
HANDLE hDrive = INVALID_HANDLE_VALUE, hVolume = INVALID_HANDLE_VALUE;
size_t len;
char path[MAX_PATH];
VOLUME_DISK_EXTENTS_REDEF DiskExtents;
DWORD size;
UINT drive_type;
int i, j;
static const char* ignore_device[] = { "\\Device\\CdRom", "\\Device\\Floppy" };
static const char* volume_start = "\\\\?\\";
StrArray found_name;
uint64_t found_offset[MAX_PARTITIONS] = { 0 };
uint32_t i, j, k;
size_t len;
StrArrayCreate(&found_name, MAX_PARTITIONS);
CheckDriveIndex(DriveIndex);
if (PartitionIndex > MAX_PARTITIONS)
goto out;
for (i = 0; hDrive == INVALID_HANDLE_VALUE; i++) {
if (i == 0) {
@ -295,7 +313,7 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent
if (GetLastError() != ERROR_NO_MORE_FILES) {
suprintf("Could not access next GUID volume: %s", WindowsErrorString());
}
goto out;
break;
}
}
@ -337,18 +355,68 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent
continue;
}
safe_closehandle(hDrive);
if ((DiskExtents.NumberOfDiskExtents >= 1) && (DiskExtents.Extents[0].DiskNumber == DriveIndex)) {
if (bKeepTrailingBackslash)
volume_name[len-1] = '\\';
success = TRUE;
if (DiskExtents.NumberOfDiskExtents == 0) {
suprintf("Ignoring volume '%s' because it has no extents...", volume_name);
continue;
}
if (DiskExtents.NumberOfDiskExtents != 1) {
// If we have more than one extent for a volume, it means that someone
// is using RAID-1 or something => Stay well away from such a volume!
suprintf("Ignoring volume '%s' because it has more than one extent (RAID?)...", volume_name);
continue;
}
if (DiskExtents.Extents[0].DiskNumber != DriveIndex)
// Not on our disk
continue;
if (found_name.Index == MAX_PARTITIONS) {
uprintf("Error: Trying to process a disk with more than %d partitions!", MAX_PARTITIONS);
goto out;
}
if (bKeepTrailingBackslash)
volume_name[len - 1] = '\\';
found_offset[found_name.Index] = DiskExtents.Extents[0].StartingOffset.QuadPart;
StrArrayAdd(&found_name, volume_name, TRUE);
// uprintf("GOT %s @%lld", volume_name, DiskExtents.Extents[0].StartingOffset.QuadPart);
}
if (found_name.Index == 0)
goto out;
// Now process all the volumes we found, and find the one that matches our partition index
if (PartitionIndex == 0) {
i = 0;
} else for (i = 0, k = 0; i < found_name.Index; i++) {
for (j = 0; j < found_name.Index; j++) {
if (found_offset[i] > found_offset[j])
k++;
}
if (k == ((int)PartitionIndex) - 1)
break;
}
if (i < found_name.Index) {
ret = safe_strdup(found_name.String[i]);
} else {
// Some volumes, such as ESPs, are not listed by Windows, be it with VDS or other APIs.
// For these, we return the "\\?\GLOBALROOT\Device\HarddiskVolume#" identifier that
// matches our "Harddisk#Partition#", as reported by QueryDosDevice().
static_sprintf(path, "Harddisk%luPartition%lu", DriveIndex, PartitionIndex);
static_strcpy(volume_name, groot_name);
if (!QueryDosDeviceA(path, &volume_name[groot_len], (DWORD)(MAX_PATH - groot_len)) || (strlen(volume_name) < 20)) {
uprintf("Could not find the DOS volume name for '%s': %s", path, WindowsErrorString());
} else {
if (bKeepTrailingBackslash)
static_strcat(volume_name, "\\");
ret = safe_strdup(volume_name);
}
}
out:
if (hVolume != INVALID_HANDLE_VALUE)
FindVolumeClose(hVolume);
return (success)?safe_strdup(volume_name):NULL;
StrArrayDestroy(&found_name);
return ret;
}
/*
@ -378,7 +446,8 @@ BOOL DeletePartitions(DWORD DriveIndex)
hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
&IID_IVdsServiceLoader, (void **)&pLoader);
if (hr != S_OK) {
uprintf("Could not create VDS Loader Instance: hr=%X\n", hr);
VDS_SET_ERROR(hr);
uprintf("Could not create VDS Loader Instance: %s", WindowsErrorString());
goto out;
}
@ -386,14 +455,16 @@ BOOL DeletePartitions(DWORD DriveIndex)
hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);
IVdsServiceLoader_Release(pLoader);
if (hr != S_OK) {
uprintf("Could not load VDS Service: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not load VDS Service: %s", WindowsErrorString());
goto out;
}
// Query the VDS Service Providers
hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
if (hr != S_OK) {
uprintf("Could not query VDS Service Providers: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not query VDS Service Providers: %s", WindowsErrorString());
goto out;
}
@ -407,7 +478,8 @@ BOOL DeletePartitions(DWORD DriveIndex)
hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider);
IUnknown_Release(pUnk);
if (hr != S_OK) {
uprintf("Could not get VDS Provider: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not get VDS Provider: %s", WindowsErrorString());
goto out;
}
@ -415,7 +487,8 @@ BOOL DeletePartitions(DWORD DriveIndex)
hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider);
IVdsProvider_Release(pProvider);
if (hr != S_OK) {
uprintf("Could not get VDS Software Provider: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not get VDS Software Provider: %s", WindowsErrorString());
goto out;
}
@ -423,7 +496,8 @@ BOOL DeletePartitions(DWORD DriveIndex)
hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack);
IVdsSwProvider_Release(pSwProvider);
if (hr != S_OK) {
uprintf("Could not get VDS Software Provider Packs: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not get VDS Software Provider Packs: %s", WindowsErrorString());
goto out;
}
@ -436,14 +510,16 @@ BOOL DeletePartitions(DWORD DriveIndex)
hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack);
IUnknown_Release(pPackUnk);
if (hr != S_OK) {
uprintf("Could not query VDS Software Provider Pack: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not query VDS Software Provider Pack: %s", WindowsErrorString());
goto out;
}
// Use the pack interface to access the disks
hr = IVdsPack_QueryDisks(pPack, &pEnumDisk);
if (hr != S_OK) {
uprintf("Could not query VDS disks: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not query VDS disks: %s", WindowsErrorString());
goto out;
}
@ -458,14 +534,16 @@ BOOL DeletePartitions(DWORD DriveIndex)
// Get the disk interface.
hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk);
if (hr != S_OK) {
uprintf("Could not query VDS Disk Interface: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not query VDS Disk Interface: %s", WindowsErrorString());
goto out;
}
// Get the disk properties
hr = IVdsDisk_GetProperties(pDisk, &diskprop);
if (hr != S_OK) {
uprintf("Could not query VDS Disk Properties: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not query VDS Disk Properties: %s", WindowsErrorString());
goto out;
}
@ -479,65 +557,58 @@ BOOL DeletePartitions(DWORD DriveIndex)
hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk);
IVdsDisk_Release(pDisk);
if (hr != S_OK) {
uprintf("Could not access VDS Advanced Disk interface: 0x%08X", hr);
VDS_SET_ERROR(hr);
uprintf("Could not access VDS Advanced Disk interface: %s", WindowsErrorString());
goto out;
}
// Query the partition data, so we can get the start offset, which we need for deletion
hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size);
if (hr != S_OK) {
uprintf("No partition to delete on disk '%ws'", diskprop.pwszName);
goto out;
}
uprintf("Deleting ALL partitions from disk '%ws':", diskprop.pwszName);
// Now go through each partition
r = (prop_array_size >= 1);
for (i = 0; i < prop_array_size; i++) {
uprintf("● Partition %d (offset: %lld, size: %s)", prop_array[i].ulPartitionNumber,
prop_array[i].ullOffset, SizeToHumanReadable(prop_array[i].ullSize, FALSE, FALSE));
hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);
if (hr != S_OK) {
r = FALSE;
uprintf("Could not delete partitions: 0x%08X", hr);
if (hr == S_OK) {
uprintf("Deleting ALL partition(s) from disk '%S':", diskprop.pwszName);
// Now go through each partition
for (i = 0; i < prop_array_size; i++) {
uprintf("● Partition %d (offset: %lld, size: %s)", prop_array[i].ulPartitionNumber,
prop_array[i].ullOffset, SizeToHumanReadable(prop_array[i].ullSize, FALSE, FALSE));
hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);
if (hr != S_OK) {
r = FALSE;
VDS_SET_ERROR(hr);
uprintf("Could not delete partitions: %s", WindowsErrorString());
}
}
r = TRUE;
} else {
uprintf("No partition to delete on disk '%S'", diskprop.pwszName);
r = TRUE;
}
CoTaskMemFree(prop_array);
// NB: In the future, we could try something like this to format partitions:
#if 0
// Initiate formatting and wait for completion.
LPWSTR pwszLabel[8] = L"TEST";
ULONGLONG Offset = 1024 * 1024;
BOOL QuickFormat = TRUE;
BOOL EnableCompression = FALSE;
IVdsAsync* pAsync;
hr = IVdsAdvancedDisk_FormatPartition(pAdvancedDisk, Offset, FileSystemType,
pwszLabel, 0, TRUE, QuickFormat, EnableCompression, &pAsync);
if (hr != S_OK) {
uprintf("Could not start formatting: 0x%08X", hr);
goto out;
}
VDS_ASYNC_OUTPUT AsyncOut;
ULONG ulPercentCompleted;
// Issue a Clean while we're at it
HRESULT hr2 = E_FAIL;
do {
hr = IVdsAsync_QueryStatus(pAsync, &hr2, &ulPercentCompleted);
ULONG completed;
IVdsAsync* pAsync;
hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, FALSE, FALSE, &pAsync);
while (SUCCEEDED(hr)) {
if (IS_ERROR(FormatStatus)) {
IVdsAsync_Cancel(pAsync);
break;
}
hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);
if (SUCCEEDED(hr)) {
printf("%ld%%", ulPercentCompleted);
if ((hr2 != S_OK) && (hr2 != VDS_E_OPERATION_PENDING)) {
uprintf("hr2: %X", hr2);
hr = hr2;
if (hr == S_OK)
break;
}
if (hr2 == S_OK) {
break;
}
if (hr == VDS_E_OPERATION_PENDING)
hr = S_OK;
}
Sleep(500);
} while (SUCCEEDED(hr));
hr = IVdsAsync_Wait(pAsync, &hr2, &AsyncOut);
IVdsAsync_Release(pAsync);
}
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not clean disk: %s", WindowsErrorString());
}
#endif
IVdsAdvancedDisk_Release(pAdvancedDisk);
goto out;
@ -551,7 +622,7 @@ out:
/* Wait for a logical drive to reappear - Used when a drive has just been repartitioned */
BOOL WaitForLogical(DWORD DriveIndex)
BOOL WaitForLogical(DWORD DriveIndex, DWORD PartitionIndex)
{
uint64_t EndTime;
char* LogicalPath = NULL;
@ -560,11 +631,13 @@ BOOL WaitForLogical(DWORD DriveIndex)
// make sure we don't spend more than DRIVE_ACCESS_TIMEOUT in wait.
EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;
do {
LogicalPath = GetLogicalName(DriveIndex, FALSE, TRUE);
if (LogicalPath != NULL) {
LogicalPath = GetLogicalName(DriveIndex, PartitionIndex, FALSE, TRUE);
// Need to filter out GlobalRoot devices as we don't want to wait on those
if ((LogicalPath != NULL) && (strncmp(LogicalPath, groot_name, groot_len) != 0)) {
free(LogicalPath);
return TRUE;
}
free(LogicalPath);
if (IS_ERROR(FormatStatus)) // User cancel
return FALSE;
Sleep(DRIVE_ACCESS_TIMEOUT/DRIVE_ACCESS_RETRIES);
@ -574,14 +647,14 @@ BOOL WaitForLogical(DWORD DriveIndex)
}
/*
* Obtain a handle to the first logical volume on the disk identified by DriveIndex
* Obtain a handle to the volume identified by DriveIndex + PartitionIndex
* Returns INVALID_HANDLE_VALUE on error or NULL if no logical path exists (typical
* of unpartitioned drives)
*/
HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare)
HANDLE GetLogicalHandle(DWORD DriveIndex, DWORD PartitionIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare)
{
HANDLE hLogical = INVALID_HANDLE_VALUE;
char* LogicalPath = GetLogicalName(DriveIndex, FALSE, FALSE);
char* LogicalPath = GetLogicalName(DriveIndex, PartitionIndex, FALSE, FALSE);
if (LogicalPath == NULL) {
uprintf("No logical drive found (unpartitioned?)");
@ -956,7 +1029,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
SelectedDrive.nPartitions = 0;
// Populate the filesystem data
FileSystemName[0] = 0;
volume_name = GetLogicalName(DriveIndex, TRUE, FALSE);
volume_name = GetLogicalName(DriveIndex, 0, TRUE, FALSE);
if ((volume_name == NULL) || (!GetVolumeInformationA(volume_name, NULL, 0, NULL, NULL, NULL, FileSystemName, FileSystemNameSize))) {
suprintf("No volume information for drive 0x%02x", DriveIndex);
}
@ -1142,49 +1215,50 @@ BOOL UnmountVolume(HANDLE hDrive)
/*
* Mount the volume identified by drive_guid to mountpoint drive_name.
* If drive_guid is already mounted, but with a different letter than the
* one requested, drive_name is updated to use that letter.
* If volume_name is already mounted, but with a different letter than the
* one requested then drive_name is updated to use that letter.
*/
BOOL MountVolume(char* drive_name, char *drive_guid)
BOOL MountVolume(char* drive_name, char *volume_name)
{
char mounted_guid[52];
char mounted_letter[27] = { 0 };
DWORD size;
if (drive_name[0] == '?')
if ((drive_name == NULL) || (volume_name == NULL) || (drive_name[0] == '?') ||
(strncmp(volume_name, groot_name, groot_len) == 0))
return FALSE;
// Windows may already have the volume mounted but under a different letter.
// If that is the case, update drive_name to that letter.
if ( (GetVolumePathNamesForVolumeNameA(drive_guid, mounted_letter, sizeof(mounted_letter), &size))
if ( (GetVolumePathNamesForVolumeNameA(volume_name, mounted_letter, sizeof(mounted_letter), &size))
&& (size > 1) && (mounted_letter[0] != drive_name[0]) ) {
uprintf("%s is already mounted as %C: instead of %C: - Will now use this target instead...",
drive_guid, mounted_letter[0], drive_name[0]);
volume_name, mounted_letter[0], drive_name[0]);
drive_name[0] = mounted_letter[0];
return TRUE;
}
if (!SetVolumeMountPointA(drive_name, drive_guid)) {
if (!SetVolumeMountPointA(drive_name, volume_name)) {
if (GetLastError() == ERROR_DIR_NOT_EMPTY) {
if (!GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid))) {
uprintf("%s is already mounted, but volume GUID could not be checked: %s",
drive_name, WindowsErrorString());
} else if (safe_strcmp(drive_guid, mounted_guid) != 0) {
} else if (safe_strcmp(volume_name, mounted_guid) != 0) {
uprintf("%s is mounted, but volume GUID doesn't match:\r\n expected %s, got %s",
drive_name, drive_guid, mounted_guid);
drive_name, volume_name, mounted_guid);
} else {
uprintf("%s is already mounted as %C:", drive_guid, drive_name[0]);
uprintf("%s is already mounted as %C:", volume_name, drive_name[0]);
return TRUE;
}
uprintf("Retrying after dismount...");
if (!DeleteVolumeMountPointA(drive_name))
uprintf("Warning: Could not delete volume mountpoint: %s", WindowsErrorString());
if (SetVolumeMountPointA(drive_name, drive_guid))
if (SetVolumeMountPointA(drive_name, volume_name))
return TRUE;
if ((GetLastError() == ERROR_DIR_NOT_EMPTY) &&
GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid)) &&
(safe_strcmp(drive_guid, mounted_guid) == 0)) {
uprintf("%s was remounted as %C: (second time lucky!)", drive_guid, drive_name[0]);
(safe_strcmp(volume_name, mounted_guid) == 0)) {
uprintf("%s was remounted as %C: (second time lucky!)", volume_name, drive_name[0]);
return TRUE;
}
}
@ -1194,85 +1268,39 @@ BOOL MountVolume(char* drive_name, char *drive_guid)
}
/*
* 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)
* Alternate version of MountVolume required for ESP's, since Windows (including VDS) does
* *NOT* provide any means of mounting these volume but through DefineDosDevice(). Also
* note the bcdboot is very finicky about what it may or may not handle, even if the
* mount was successful (e.g. '\Device\HarddiskVolume###' vs 'Device\HarddiskVolume###').
* Returned string is static (no concurrency) and should not be freed.
*/
char* AltMountVolume(const char* drive_name, uint8_t part_nr)
char* AltMountVolume(DWORD DriveIndex, DWORD PartitionIndex)
{
char* ret = NULL, *volume_name = NULL;
static char mounted_drive[] = "?:";
const DWORD bufsize = 65536;
char *buffer = NULL, *p, target[2][MAX_PATH], *ret = NULL;
size_t 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 volume name for '%s': %s", drive_name, WindowsErrorString());
volume_name = GetLogicalName(DriveIndex, PartitionIndex, FALSE, TRUE);
if ((volume_name == NULL) || (strncmp(volume_name, groot_name, groot_len) != 0)) {
uprintf("Unexpected volume name: '%s'", volume_name);
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());
// bcdboot sure won't like it if you forget the starting '\'
if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH | DDD_NO_BROADCAST_SYSTEM, mounted_drive, &volume_name[14])) {
uprintf("Could not mount '%s' to '%s': %s", &volume_name[14], mounted_drive, 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 find the DOS volume name for partition '%s': %s", p, 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);
uprintf("Successfully mounted '%s' (Partition %d) as '%s'", &volume_name[14], PartitionIndex, mounted_drive);
ret = mounted_drive;
out:
safe_free(buffer);
free(volume_name);
return ret;
}
@ -1297,23 +1325,23 @@ BOOL AltUnmountVolume(const char* drive_name)
*/
BOOL RemountVolume(char* drive_name)
{
char drive_guid[51];
char volume_name[51];
// UDF requires a sync/flush, and it's also a good idea for other FS's
FlushDrive(drive_name[0]);
if (GetVolumeNameForVolumeMountPointA(drive_name, drive_guid, sizeof(drive_guid))) {
if (GetVolumeNameForVolumeMountPointA(drive_name, volume_name, sizeof(volume_name))) {
if (DeleteVolumeMountPointA(drive_name)) {
Sleep(200);
if (MountVolume(drive_name, drive_guid)) {
uprintf("Successfully remounted %s as %C:", drive_guid, drive_name[0]);
if (MountVolume(drive_name, volume_name)) {
uprintf("Successfully remounted %s as %C:", volume_name, drive_name[0]);
} else {
uprintf("Failed to remount %s as %C:", drive_guid, drive_name[0]);
uprintf("Failed to remount %s as %C:", volume_name, drive_name[0]);
// This will leave the drive inaccessible and must be flagged as an error
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_REMOUNT_VOLUME);
return FALSE;
}
} else {
uprintf("Could not remount %s as %C: %s", drive_guid, drive_name[0], WindowsErrorString());
uprintf("Could not remount %s as %C: %s", volume_name, drive_name[0], WindowsErrorString());
// Try to continue regardless
}
}
@ -1328,7 +1356,7 @@ typedef struct _DRIVE_LAYOUT_INFORMATION_EX4 {
DRIVE_LAYOUT_INFORMATION_MBR Mbr;
DRIVE_LAYOUT_INFORMATION_GPT Gpt;
} Type;
PARTITION_INFORMATION_EX PartitionEntry[4];
PARTITION_INFORMATION_EX PartitionEntry[MAX_PARTITIONS];
} DRIVE_LAYOUT_INFORMATION_EX4,*PDRIVE_LAYOUT_INFORMATION_EX4;
/*
@ -1341,13 +1369,14 @@ typedef struct _DRIVE_LAYOUT_INFORMATION_EX4 {
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, uint8_t extra_partitions)
{
const char* PartitionTypeName[] = { "MBR", "GPT", "SFD" };
const wchar_t* extra_part_name;
unsigned char* buffer;
size_t uefi_ntfs_size = 0;
CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}};
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, ms_efi_size;
LONGLONG main_part_size_in_sectors, extra_part_size_in_tracks = 0, ms_esp_size;
const LONGLONG bytes_per_track = ((LONGLONG)SelectedDrive.SectorsPerTrack) * SelectedDrive.SectorSize;
PrintInfoDebug(0, MSG_238, PartitionTypeName[partition_style]);
@ -1361,6 +1390,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
if (uefi_ntfs_size == 0)
return FALSE;
}
memset(partition_index, 0, sizeof(partition_index));
// Compute the start offset of our first partition
if ((partition_style == PARTITION_STYLE_GPT) || (!IsChecked(IDC_OLD_BIOS_FIXES))) {
@ -1371,14 +1401,43 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = bytes_per_track;
}
// If required, set the ESP (which Microsoft wants to be the first)
if (extra_partitions & XP_ESP) {
uprintf("● Creating EFI System Partition");
// The size of the ESP 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.
// Plus some people are complaining that the *OFFICIAL MINIMUM SIZE* as documented by Microsoft at
// https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/configure-uefigpt-based-hard-drive-partitions
// is too small. See: https://github.com/pbatard/rufus/issues/979
if (SelectedDrive.SectorSize <= 4096)
ms_esp_size = 300 * MB;
else
ms_esp_size = 1200 * MB; // That'll teach you to have a nonstandard disk!
extra_part_size_in_tracks = (ms_esp_size + bytes_per_track - 1) / bytes_per_track;
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = extra_part_size_in_tracks * bytes_per_track;
if (partition_style == PARTITION_STYLE_GPT) {
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_SYSTEM_GUID;
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
// coverity[strcpy_overrun]
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, L"EFI System Partition");
} else {
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0xef;
}
pn++;
partition_index[PI_ESP] = pn;
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn - 1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn - 1].PartitionLength.QuadPart;
}
// If required, set the MSR partition (GPT only - must be created before the data part)
if ((partition_style == PARTITION_STYLE_GPT) && (extra_partitions & XP_MSR)) {
uprintf("Adding MSR partition");
uprintf("● Creating MSR Partition");
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = 128*MB;
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_MSFT_RESERVED_GUID;
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
// coverity[strcpy_overrun]
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, L"Microsoft reserved partition");
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, L"Microsoft Reserved Partition");
// 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)) {
@ -1390,49 +1449,45 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
free(buffer);
}
}
pn++;
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
}
// Clear the extra partitions we processed
extra_partitions &= ~(XP_ESP|XP_MSR);
// 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.SectorSize - ((partition_style == PARTITION_STYLE_GPT)?33:0);
if (main_part_size_in_sectors <= 0)
return FALSE;
// Adjust the size according to extra partitions (which we always align to a track)
if (extra_partitions) {
uprintf("Adding %s partition", (extra_partitions & XP_CASPER) ? "casper-rw": "extra");
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.
// Plus some people are complaining that the *OFFICIAL MINIMUM SIZE* as documented by Microsoft at
// https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/configure-uefigpt-based-hard-drive-partitions
// is too small. See: https://github.com/pbatard/rufus/issues/979
if (SelectedDrive.SectorSize <= 4096)
ms_efi_size = 300*MB;
else
ms_efi_size = 1200*MB; // 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_NTFS) {
if (!extra_partitions) {
uprintf("● Creating Main Data Partition: %lld tracks (%s)", main_part_size_in_sectors / SelectedDrive.SectorsPerTrack,
SizeToHumanReadable(main_part_size_in_sectors * SelectedDrive.SectorSize, TRUE, FALSE));
} else {
// Adjust the size according to extra partitions (which we always align to a track)
if (extra_partitions & XP_UEFI_NTFS) {
extra_part_name = L"UEFI:NTFS";
extra_part_size_in_tracks = (max(MIN_EXTRA_PART_SIZE, uefi_ntfs_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
} else if ((extra_partitions & XP_CASPER)) {
assert(persistence_size != 0);
extra_part_name = L"Linux Persistence";
extra_part_size_in_tracks = persistence_size / bytes_per_track;
} else if (extra_partitions & XP_COMPAT) {
extra_part_name = L"BIOS Compatibility";
extra_part_size_in_tracks = 1; // One track for the extra partition
}
uprintf("Reserved %" PRIi64" tracks (%s) for %s partition", extra_part_size_in_tracks,
SizeToHumanReadable(extra_part_size_in_tracks * bytes_per_track, TRUE, FALSE),
(extra_partitions & XP_CASPER) ? "casper-rw" : "extra");
main_part_size_in_sectors = ((main_part_size_in_sectors / SelectedDrive.SectorsPerTrack) -
extra_part_size_in_tracks) * SelectedDrive.SectorsPerTrack;
if (main_part_size_in_sectors <= 0)
return FALSE;
uprintf("● Creating Main Data Partition: %lld tracks (%s)", main_part_size_in_sectors / SelectedDrive.SectorsPerTrack,
SizeToHumanReadable(main_part_size_in_sectors * SelectedDrive.SectorSize, TRUE, FALSE));
uprintf("● Creating %S Partition: %lld tracks (%s)", extra_part_name, extra_part_size_in_tracks,
SizeToHumanReadable(extra_part_size_in_tracks * bytes_per_track, TRUE, FALSE));
}
if (main_part_size_in_sectors <= 0) {
uprintf("Error: Invalid Main Partition size!");
return FALSE;
}
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = main_part_size_in_sectors * SelectedDrive.SectorSize;
if (partition_style == PARTITION_STYLE_MBR) {
DriveLayoutEx.PartitionEntry[pn].Mbr.BootIndicator = (boot_type != BT_NON_BOOTABLE);
@ -1446,6 +1501,11 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
case FS_REFS:
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x07;
break;
case FS_EXT2:
case FS_EXT3:
case FS_EXT4:
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x83;
break;
case FS_FAT32:
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x0c; // FAT32 LBA
break;
@ -1456,61 +1516,49 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
} else {
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_BASIC_DATA_GUID;
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, L"Microsoft Basic Data");
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, L"Basic Data");
}
pn++;
partition_index[PI_MAIN] = pn;
// Set the optional extra partition
if (extra_partitions) {
// Don't forget to set our peristent partition index!
if (extra_partitions & XP_CASPER)
partition_index[PI_CASPER] = pn + 1;
// 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 = (extra_partitions & XP_UEFI_NTFS)?uefi_ntfs_size:
extra_part_size_in_tracks * bytes_per_track;
if (partition_style == PARTITION_STYLE_GPT) {
const wchar_t* name = L"Basic Data";
const GUID* guid = &PARTITION_BASIC_DATA_GUID;
if (extra_partitions & XP_EFI) {
guid = &PARTITION_SYSTEM_GUID;
name = L"EFI system partition";
} else if (extra_partitions & XP_CASPER) {
// TODO: We may also want to use PARTITION_LINUX_HOME_GUID as fallback
// to automout as /home in case casper-rw fails.
name = L"casper-rw"; // Just in case
} else if (extra_partitions & XP_UEFI_NTFS) {
name = L"UEFI:NTFS";
} else {
assert(FALSE);
}
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = *guid;
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_BASIC_DATA_GUID;
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, name);
wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, extra_part_name);
} else {
BYTE type = 0;
if (extra_partitions & XP_UEFI_NTFS) {
type = 0xef;
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0xef;
} else if (extra_partitions & XP_CASPER) {
type = 0x83;
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x83;
} else if (extra_partitions & XP_COMPAT) {
type = RUFUS_EXTRA_PARTITION_TYPE;
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = RUFUS_EXTRA_PARTITION_TYPE;
// Set the one track compatibility partition to be all hidden sectors
DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.SectorsPerTrack;
} else {
assert(FALSE);
}
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = type;
}
// We need to write the UEFI:NTFS partition before we refresh the disk
if (extra_partitions & XP_UEFI_NTFS) {
uprintf("Writing UEFI:NTFS partition...");
uprintf("Writing %S data...", extra_part_name);
if (!SetFilePointerEx(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, NULL, FILE_BEGIN)) {
uprintf("Unable to set position");
uprintf("Could not set position");
return FALSE;
}
buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_NTFS), _RT_RCDATA, "uefi-ntfs.img", &bufsize, FALSE);
if (buffer == NULL) {
uprintf("Could not access uefi-ntfs.img");
uprintf("Could not access source image");
return FALSE;
}
if(!WriteFileWithRetry(hDrive, buffer, bufsize, &size, WRITE_RETRIES)) {
@ -1524,7 +1572,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
// Initialize the remaining partition data
for (i = 0; i < pn; i++) {
DriveLayoutEx.PartitionEntry[i].PartitionNumber = i+1;
DriveLayoutEx.PartitionEntry[i].PartitionNumber = i + 1;
DriveLayoutEx.PartitionEntry[i].PartitionStyle = partition_style;
DriveLayoutEx.PartitionEntry[i].RewritePartition = TRUE;
}
@ -1552,14 +1600,14 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
CreateDisk.PartitionStyle = PARTITION_STYLE_GPT;
IGNORE_RETVAL(CoCreateGuid(&CreateDisk.Gpt.DiskId));
CreateDisk.Gpt.MaxPartitionCount = MAX_GPT_PARTITIONS;
CreateDisk.Gpt.MaxPartitionCount = MAX_PARTITIONS;
DriveLayoutEx.PartitionStyle = PARTITION_STYLE_GPT;
DriveLayoutEx.PartitionCount = pn;
// At the very least, a GPT disk has 34 reserved sectors at the beginning and 33 at the end.
DriveLayoutEx.Type.Gpt.StartingUsableOffset.QuadPart = 34 * SelectedDrive.SectorSize;
DriveLayoutEx.Type.Gpt.UsableLength.QuadPart = SelectedDrive.DiskSize - (34+33) * SelectedDrive.SectorSize;
DriveLayoutEx.Type.Gpt.MaxPartitionCount = MAX_GPT_PARTITIONS;
DriveLayoutEx.Type.Gpt.MaxPartitionCount = MAX_PARTITIONS;
DriveLayoutEx.Type.Gpt.DiskId = CreateDisk.Gpt.DiskId;
break;
}

View file

@ -33,13 +33,27 @@
CTL_CODE(MOUNTMGRCONTROLTYPE, 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define XP_MSR 0x01
#define XP_EFI 0x02
#define XP_ESP 0x02
#define XP_UEFI_NTFS 0x04
#define XP_COMPAT 0x08
#define XP_CASPER 0x10
#define PI_MAIN 0
#define PI_ESP 1
#define PI_CASPER 2
// The following should match VDS_FSOF_FLAGS as much as possible
#define FP_FORCE 0x00000001
#define FP_QUICK 0x00000002
#define FP_COMPRESSION 0x00000004
#define FP_DUPLICATE_METADATA 0x00000008
#define FP_LARGE_FAT32 0x00010000
#define FP_NO_BOOT 0x00020000
#define FILE_FLOPPY_DISKETTE 0x00000004
#define VDS_SET_ERROR(hr) do { if (hr == S_FALSE) hr = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE; FormatStatus = hr; SetLastError(hr); } while(0)
#if !defined(__MINGW32__)
typedef enum _FSINFOCLASS {
FileFsVolumeInformation = 1,
@ -87,6 +101,25 @@ typedef interface IVdsDisk IVdsDisk;
typedef interface IVdsAdvancedDisk IVdsAdvancedDisk;
typedef interface IVdsAdviseSink IVdsAdviseSink;
typedef interface IVdsAsync IVdsAsync;
typedef interface IVdsVolume IVdsVolume;
typedef interface IVdsVolumeMF3 IVdsVolumeMF3;
extern const IID CLSID_VdsLoader;
extern const IID IID_IVdsServiceLoader;
extern const IID IID_IVdsProvider;
extern const IID IID_IVdsSwProvider;
extern const IID IID_IVdsPack;
extern const IID IID_IVdsDisk;
extern const IID IID_IVdsAdvancedDisk;
extern const IID IID_IVdsVolume;
extern const IID IID_IVdsVolumeMF3;
#ifndef VDS_S_PROPERTIES_INCOMPLETE
#define VDS_S_PROPERTIES_INCOMPLETE ((HRESULT)0x00042715L)
#endif
#ifndef VDS_E_OPERATION_PENDING
#define VDS_E_OPERATION_PENDING ((HRESULT)0x80042409L)
#endif
typedef struct IVdsServiceLoaderVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsServiceLoader *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
@ -212,21 +245,77 @@ interface IVdsAdvancedDisk {
CONST_VTBL struct IVdsAdvancedDiskVtbl *lpVtbl;
};
#define IVdsServiceLoader_LoadService(This,pwszMachineName,ppService) (This)->lpVtbl->LoadService(This,pwszMachineName,ppService)
typedef struct IVdsVolumeVtbl {
HRESULT (STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsVolume *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsVolume *This);
ULONG (STDMETHODCALLTYPE *Release)(__RPC__in IVdsVolume *This);
HRESULT (STDMETHODCALLTYPE *GetProperties)(__RPC__in IVdsVolume *This, __RPC__out VDS_VOLUME_PROP *pVolumeProperties);
HRESULT (STDMETHODCALLTYPE *GetPack)(__RPC__in IVdsVolume *This, __RPC__deref_out_opt IVdsPack **ppPack);
HRESULT (STDMETHODCALLTYPE *QueryPlexes)(__RPC__in IVdsVolume *This, __RPC__deref_out_opt IEnumVdsObject **ppEnum);
HRESULT (STDMETHODCALLTYPE *Extend)(__RPC__in IVdsVolume *This, __RPC__in_ecount_full_opt(lNumberOfDisks) VDS_INPUT_DISK *pInputDiskArray, LONG lNumberOfDisks, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT (STDMETHODCALLTYPE *Shrink)(__RPC__in IVdsVolume *This, ULONGLONG ullNumberOfBytesToRemove, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT (STDMETHODCALLTYPE *AddPlex)(__RPC__in IVdsVolume *This, VDS_OBJECT_ID VolumeId,__RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT (STDMETHODCALLTYPE *BreakPlex)(__RPC__in IVdsVolume *This, VDS_OBJECT_ID plexId, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT (STDMETHODCALLTYPE *RemovePlex)(__RPC__in IVdsVolume *This, VDS_OBJECT_ID plexId, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT (STDMETHODCALLTYPE *Delete)(__RPC__in IVdsVolume *This, BOOL bForce);
HRESULT (STDMETHODCALLTYPE *SetFlags)(__RPC__in IVdsVolume *This, ULONG ulFlags, BOOL bRevertOnClose);
HRESULT (STDMETHODCALLTYPE *ClearFlags)(__RPC__in IVdsVolume *This, ULONG ulFlags);
} IVdsVolumeVtbl;
interface IVdsVolume {
CONST_VTBL struct IVdsVolumeVtbl *lpVtbl;
};
typedef struct IVdsVolumeMF3Vtbl {
HRESULT (STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsVolumeMF3 *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsVolumeMF3 *This);
ULONG (STDMETHODCALLTYPE *Release)(__RPC__in IVdsVolumeMF3 *This);
HRESULT (STDMETHODCALLTYPE *QueryVolumeGuidPathnames)(__RPC__in IVdsVolumeMF3 *This, __RPC__deref_out_ecount_full_opt_string(*pulNumberOfPaths) LPWSTR **pwszPathArray, __RPC__out ULONG *pulNumberOfPaths);
HRESULT (STDMETHODCALLTYPE *FormatEx2)(__RPC__in IVdsVolumeMF3 *This, __RPC__in_opt_string LPWSTR pwszFileSystemTypeName, USHORT usFileSystemRevision, ULONG ulDesiredUnitAllocationSize, __RPC__in_opt_string LPWSTR pwszLabel, DWORD Options, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT (STDMETHODCALLTYPE *OfflineVolume)(__RPC__in IVdsVolumeMF3 *This);
} IVdsVolumeMF3Vtbl;
interface IVdsVolumeMF3 {
CONST_VTBL struct IVdsVolumeMF3Vtbl *lpVtbl;
};
typedef struct IVdsAsyncVtbl {
HRESULT (STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsAsync *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsAsync *This);
ULONG (STDMETHODCALLTYPE *Release)(__RPC__in IVdsAsync *This);
HRESULT (STDMETHODCALLTYPE *Cancel)(__RPC__in IVdsAsync *This);
HRESULT (STDMETHODCALLTYPE *Wait)(__RPC__in IVdsAsync *This, __RPC__out HRESULT *pHrResult, __RPC__out VDS_ASYNC_OUTPUT *pAsyncOut);
HRESULT (STDMETHODCALLTYPE *QueryStatus)(__RPC__in IVdsAsync *This, __RPC__out HRESULT *pHrResult, __RPC__out ULONG *pulPercentCompleted);
} IVdsAsyncVtbl;
interface IVdsAsync {
CONST_VTBL struct IVdsAsyncVtbl *lpVtbl;
};
#define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService)
#define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This)
#define IVdsService_QueryProviders(This,masks,ppEnum) (This)->lpVtbl->QueryProviders(This,masks,ppEnum)
#define IVdsSwProvider_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
#define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum)
#define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
#define IVdsProvider_Release(This) (This)->lpVtbl->Release(This)
#define IVdsSwProvider_QueryPacks(This,ppEnum) (This)->lpVtbl->QueryPacks(This,ppEnum)
#define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum)
#define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This)
#define IVdsPack_QueryDisks(This,ppEnum) (This)->lpVtbl->QueryDisks(This,ppEnum)
#define IVdsDisk_GetProperties(This,pDiskProperties) (This)->lpVtbl->GetProperties(This,pDiskProperties)
#define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum)
#define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties)
#define IVdsDisk_Release(This) (This)->lpVtbl->Release(This)
#define IVdsDisk_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
#define IVdsAdvancedDisk_QueryPartitions(This,ppPartitionPropArray,plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This,ppPartitionPropArray,plNumberOfPartitions)
#define IVdsAdvancedDisk_DeletePartition(This,ullOffset,bForce,bForceProtected) (This)->lpVtbl->DeletePartition(This,ullOffset,bForce,bForceProtected)
#define IVdsDisk_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
#define IVdsAdvancedDisk_QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions)
#define IVdsAdvancedDisk_DeletePartition(This, ullOffset, bForce, bForceProtected) (This)->lpVtbl->DeletePartition(This, ullOffset, bForce, bForceProtected)
#define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync)
#define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)
#define IEnumVdsObject_Next(This,celt,ppObjectArray,pcFetched) (This)->lpVtbl->Next(This,celt,ppObjectArray,pcFetched)
#define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched)
#define IVdsPack_QueryVolumes(This, ppEnum) (This)->lpVtbl->QueryVolumes(This, ppEnum)
#define IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
#define IVdsVolume_Release(This) (This)->lpVtbl->Release(This)
#define IVdsVolumeMF3_QueryVolumeGuidPathnames(This, pwszPathArray, pulNumberOfPaths) (This)->lpVtbl->QueryVolumeGuidPathnames(This,pwszPathArray,pulNumberOfPaths)
#define IVdsVolumeMF3_FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) (This)->lpVtbl->FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync)
#define IVdsVolumeMF3_Release(This) (This)->lpVtbl->Release(This)
#define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties)
#define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This)
#define IVdsAsync_QueryStatus(This,pHrResult,pulPercentCompleted) (This)->lpVtbl->QueryStatus(This,pHrResult,pulPercentCompleted)
#define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut)
#define IVdsAsync_Release(This) (This)->lpVtbl->Release(This)
#endif
static __inline BOOL UnlockDrive(HANDLE hDrive) {
@ -256,16 +345,17 @@ typedef struct {
} RUFUS_DRIVE_INFO;
extern RUFUS_DRIVE_INFO SelectedDrive;
extern uint64_t persistence_size;
extern DWORD partition_index[3];
BOOL SetAutoMount(BOOL enable);
BOOL GetAutoMount(BOOL* enabled);
char* GetPhysicalName(DWORD DriveIndex);
char* GetPartitionName(DWORD DriveIndex, DWORD PartitionNumber);
char* GetPartitionName(DWORD DriveIndex, DWORD PartitionIndex);
BOOL DeletePartitions(DWORD DriveIndex);
HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent);
BOOL WaitForLogical(DWORD DriveIndex);
HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
char* GetLogicalName(DWORD DriveIndex, DWORD PartitionIndex, BOOL bKeepTrailingBackslash, BOOL bSilent);
BOOL WaitForLogical(DWORD DriveIndex, DWORD PartitionIndex);
HANDLE GetLogicalHandle(DWORD DriveIndex, DWORD PartitionIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
int GetDriveNumber(HANDLE hDrive, char* path);
BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters);
UINT GetDriveTypeFromIndex(DWORD DriveIndex);
@ -279,7 +369,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
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);
char* AltMountVolume(DWORD DriveIndex, DWORD PartitionIndex);
BOOL RemountVolume(char* drive_name);
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, uint8_t extra_partitions);
BOOL InitializeDisk(HANDLE hDrive);

File diff suppressed because it is too large Load diff

View file

@ -85,6 +85,10 @@ static __inline char* wchar_to_utf8(const wchar_t* wstr)
int size = 0;
char* str = NULL;
// Convert the empty string too
if (wstr[0] == 0)
return calloc(1, 1);
// Find out the size we need to allocate for our converted string
size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
if (size <= 1) // An empty string would be size 1
@ -113,6 +117,10 @@ static __inline wchar_t* utf8_to_wchar(const char* str)
if (str == NULL)
return NULL;
// Convert the empty string too
if (str[0] == 0)
return calloc(1, sizeof(wchar_t));
// Find out the size we need to allocate for our converted string
size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
if (size <= 1) // An empty string would be size 1

View file

@ -51,7 +51,6 @@
#include "../res/grub2/grub2_version.h"
static const char* cmdline_hogger = "rufus.com";
static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "UDF", "exFAT", "ReFS" };
static const char* ep_reg = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer";
static const char* vs_reg = "Software\\Microsoft\\VisualStudio";
static BOOL existing_key = FALSE; // For LGP set/restore
@ -84,6 +83,7 @@ extern long grub2_len;
extern char* szStatusMessage;
extern const char* old_c32_name[NB_OLD_C32];
extern const char* cert_name[3];
extern const char* FileSystemLabel[FS_MAX];
/*
* Globals
@ -108,7 +108,7 @@ BOOL enable_HDDs = FALSE, enable_ntfs_compression = FALSE, no_confirmation_on_ca
BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fakes, enable_vmdk, force_large_fat32, usb_debug;
BOOL use_fake_units, preserve_timestamps = FALSE, fast_zeroing = FALSE, app_changed_size = FALSE;
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE;
BOOL write_as_image = FALSE, installed_uefi_ntfs = FALSE, enable_fido = FALSE;
BOOL write_as_image = FALSE, installed_uefi_ntfs = FALSE, enable_fido = FALSE, use_vds = FALSE;
float fScale = 1.0f;
int dialog_showing = 0, selection_default = BT_IMAGE, windows_to_go_selection = 0, persistence_unit_selection = -1;
int default_fs, fs_type, boot_type, partition_type, target_type; // file system, boot type, partition type, target type
@ -121,7 +121,7 @@ char msgbox[1024], msgbox_title[32], *ini_file = NULL, *image_path = NULL, *shor
char image_option_txt[128], *fido_url = NULL;
StrArray DriveID, DriveLabel, DriveHub, BlockingProcess, ImageList;
// Number of steps for each FS for FCC_STRUCTURE_PROGRESS
const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10 };
const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10, 1, 1, 1, 1 };
const char* flash_type[BADLOCKS_PATTERN_TYPES] = { "SLC", "MLC", "TLC" };
// TODO: Remember to update copyright year in stdlg's AboutCallback() WM_INITDIALOG,
@ -1859,10 +1859,6 @@ out:
return ret;
}
#ifdef RUFUS_TEST
extern BOOL FormatExtFs(const char* label, uint32_t version);
#endif
/*
* Main dialog callback
*/
@ -1898,7 +1894,15 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case WM_COMMAND:
#ifdef RUFUS_TEST
if (LOWORD(wParam) == IDC_TEST) {
FormatExtFs("casper-rw", 3);
// uprintf(" IID_IVdsVolume: %s", GuidToString(&IID_IVdsVolume));
// uprintf(" IID_IVdsVolumeMF3: %s", GuidToString(&IID_IVdsVolumeMF3));
nDeviceIndex = ComboBox_GetCurSel(hDeviceList);
// AltMountVolume2("G:", 3);
AltMountVolume((DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex), 3);
// AltUnmountVolume("P:");
// uprintf("%s", GetLogicalName((DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex), 0, FALSE, FALSE));
// uprintf("%s", GetLogicalName((DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex), 1, FALSE, FALSE));
// uprintf("%s", GetLogicalName((DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex), 2, FALSE, FALSE));
break;
}
#endif
@ -3026,6 +3030,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
advanced_mode_format = ReadSettingBool(SETTING_ADVANCED_MODE_FORMAT);
preserve_timestamps = ReadSettingBool(SETTING_PRESERVE_TIMESTAMPS);
use_fake_units = !ReadSettingBool(SETTING_USE_PROPER_SIZE_UNITS);
use_vds = ReadSettingBool(SETTING_USE_VDS);
usb_debug = ReadSettingBool(SETTING_ENABLE_USB_DEBUG);
detect_fakes = !ReadSettingBool(SETTING_DISABLE_FAKE_DRIVES_CHECK);
allow_dual_uefi_bios = ReadSettingBool(SETTING_ENABLE_WIN_DUAL_EFI_BIOS);
@ -3198,7 +3203,7 @@ relaunch:
// Do our own event processing and process "magic" commands
while(GetMessage(&msg, NULL, 0, 0)) {
// ** ***** **** ** ***** ****
// ** ***** **** ** **********
// .,ABCDEFGHIJKLMNOPQRSTUVWXYZ
// Ctrl-A => Select the log data
@ -3357,6 +3362,13 @@ relaunch:
GetDevices(0);
continue;
}
// Alt-V => Use VDS facilities for formatting
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'V')) {
use_vds = !use_vds;
WriteSettingBool(SETTING_USE_VDS, use_vds);
PrintStatusTimeout("VDS", use_vds);
continue;
}
// Alt-W => Enable VMWare disk detection
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'W')) {
enable_vmdk = !enable_vmdk;

View file

@ -22,13 +22,16 @@
#if defined(_MSC_VER)
// Disable some VS Code Analysis warnings
#pragma warning(disable: 4996) // Ignore deprecated
#pragma warning(disable: 28159) // I'll keep using GetVersionEx(), thank you very much!
#pragma warning(disable: 6258) // I know what I'm using TerminateThread for
#pragma warning(disable: 26451) // Stop bugging me with casts already!
#pragma warning(disable: 28159) // I'll keep using GetVersionEx(), thank you very much...
#endif
#pragma once
/* 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 APPLICATION_NAME "Rufus"
@ -67,7 +70,7 @@
#define MAX_LOG_SIZE 0x7FFFFFFE
#define MAX_REFRESH 25 // How long we should wait to refresh UI elements (in ms)
#define MAX_GUID_STRING_LENGTH 40
#define MAX_GPT_PARTITIONS 128
#define MAX_PARTITIONS 16 // Maximum number of partitions we handle
#define MAX_SECTORS_TO_CLEAR 128 // nb sectors to zap when clearing the MBR/GPT (must be >34)
#define MAX_WININST 4 // Max number of install[.wim|.esd] we can handle on an image
#define MBR_UEFI_MARKER 0x49464555 // 'U', 'E', 'F', 'I', as a 32 bit little endian longword
@ -80,7 +83,6 @@
#define CHECK_DRIVE_TIMEOUT 2000
#define MARQUEE_TIMER_REFRESH 10 // Time between progress bar marquee refreshes, in ms
#define FS_DEFAULT FS_FAT32
#define CASPER_PARTITION_DEFAULT 2
#define SINGLE_CLUSTERSIZE_DEFAULT 0x00000100
#define BADLOCKS_PATTERN_TYPES 3
#define BADBLOCK_PATTERN_COUNT 4
@ -118,7 +120,7 @@
#endif
#define IsChecked(CheckBox_ID) (IsDlgButtonChecked(hMainDialog, CheckBox_ID) == BST_CHECKED)
#define MB_IS_RTL (right_to_left_mode?MB_RTLREADING|MB_RIGHT:0)
#define CHECK_FOR_USER_CANCEL if (IS_ERROR(FormatStatus)) goto out
#define CHECK_FOR_USER_CANCEL if (IS_ERROR(FormatStatus) && (SCODE_CODE(FormatStatus) == ERROR_CANCELLED)) goto out
// Bit masks used for the display of additional image options in the UI
#define IMOP_WINTOGO 0x01
#define IMOP_PERSISTENCE 0x02
@ -243,6 +245,9 @@ enum fs_type {
FS_UDF,
FS_EXFAT,
FS_REFS,
FS_EXT2,
FS_EXT3,
FS_EXT4,
FS_MAX
};

View file

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 3.6.1527"
CAPTION "Rufus 3.6.1528"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -394,8 +394,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,6,1527,0
PRODUCTVERSION 3,6,1527,0
FILEVERSION 3,6,1528,0
PRODUCTVERSION 3,6,1528,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -413,13 +413,13 @@ BEGIN
VALUE "Comments", "https://akeo.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.6.1527"
VALUE "FileVersion", "3.6.1528"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus-3.6.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.6.1527"
VALUE "ProductVersion", "3.6.1528"
END
END
BLOCK "VarFileInfo"

View file

@ -43,8 +43,10 @@ extern char* ini_file;
#define SETTING_LAST_UPDATE "LastUpdateCheck"
#define SETTING_LOCALE "Locale"
#define SETTING_UPDATE_INTERVAL "UpdateCheckInterval"
#define SETTING_USE_EXTFS_VERSION "UseExtFsVersion"
#define SETTING_USE_EXT_VERSION "UseExtVersion"
#define SETTING_USE_PROPER_SIZE_UNITS "UseProperSizeUnits"
#define SETTING_USE_UDF_VERSION "UseUdfVersion"
#define SETTING_USE_VDS "UseVds"
#define SETTING_PRESERVE_TIMESTAMPS "PreserveTimestamps"
#define SETTING_VERBOSE_UPDATES "VerboseUpdateCheck"

View file

@ -272,7 +272,7 @@ const char* _StrError(DWORD error_code)
return lmprintf(MSG_050);
}
if (SCODE_FACILITY(error_code) != FACILITY_STORAGE) {
uprintf("StrError: non storage - %08X (%X)\n", error_code, SCODE_FACILITY(error_code));
// uprintf("StrError: non storage - %08X (%X)\n", error_code, SCODE_FACILITY(error_code));
SetLastError(error_code);
return WindowsErrorString();
}

View file

@ -136,7 +136,7 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int file_system)
* weird reason.the Syslinux install process *MUST* have FILE_SHARE_WRITE
* on the volume, or else creating 'ldlinux.sys' will fail...
*/
d_handle = GetLogicalHandle(drive_index, FALSE, TRUE, TRUE);
d_handle = GetLogicalHandle(drive_index, 0, FALSE, TRUE, TRUE);
if ((d_handle == INVALID_HANDLE_VALUE) || (d_handle == NULL)) {
uprintf("Could open volume for Syslinux installation");
goto out;

View file

@ -43,7 +43,7 @@
UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU;
HIMAGELIST hUpImageList, hDownImageList;
extern BOOL enable_fido;
extern BOOL enable_fido, use_vds;
int advanced_device_section_height, advanced_format_section_height;
// (empty) check box width, (empty) drop down width, button height (for and without dropdown match)
int cbw, ddw, ddbh = 0, bh = 0;
@ -1168,20 +1168,21 @@ void InitProgress(BOOL bOnlyFormat)
nb_slots[OP_ZERO_MBR] = 1;
nb_slots[OP_PARTITION] = 1;
nb_slots[OP_FIX_MBR] = 1;
nb_slots[OP_CREATE_FS] =
nb_slots[OP_CREATE_FS] = (use_vds) ? 2 :
nb_steps[ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem))];
// So, yeah, if you're doing slow format, or using Large FAT32, and have persistence, you'll see
// the progress bar revert during format on account that we reuse the same operation for both
// partitions. Maybe one day I'll be bothered to handle two separate OP_FORMAT ops...
if ((!IsChecked(IDC_QUICK_FORMAT)) || (persistence_size != 0)
|| ((fs_type == FS_FAT32) && ((SelectedDrive.DiskSize >= LARGE_FAT32_SIZE) || (force_large_fat32)))) {
if ((!IsChecked(IDC_QUICK_FORMAT)) || (persistence_size != 0) ||
((fs_type == FS_FAT32) && ((SelectedDrive.DiskSize >= LARGE_FAT32_SIZE) || (force_large_fat32)))) {
nb_slots[OP_FORMAT] = -1;
nb_slots[OP_CREATE_FS] = 0;
}
nb_slots[OP_FINALIZE] = ((selection_default == BT_IMAGE) && (fs_type == FS_NTFS)) ? 3 : 2;
}
}
for (i = 0; i<OP_MAX; i++) {
for (i = 0; i < OP_MAX; i++) {
if (nb_slots[i] > 0) {
slots_discrete += nb_slots[i] * 1.0f;
}
@ -1190,7 +1191,7 @@ void InitProgress(BOOL bOnlyFormat)
}
}
for (i = 0; i<OP_MAX; i++) {
for (i = 0; i < OP_MAX; i++) {
if (nb_slots[i] == 0) {
slot_end[i + 1] = last_end;
} else if (nb_slots[i] > 0) {
@ -1203,7 +1204,7 @@ void InitProgress(BOOL bOnlyFormat)
// If there's no analog, adjust our discrete ends to fill the whole bar
if (slots_analog == 0.0f) {
for (i = 0; i<OP_MAX; i++) {
for (i = 0; i < OP_MAX; i++) {
slot_end[i + 1] *= 100.0f / slots_discrete;
}
}