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:
		
							parent
							
								
									4b38483a68
								
							
						
					
					
						commit
						1c39a80d72
					
				
					 11 changed files with 955 additions and 509 deletions
				
			
		
							
								
								
									
										486
									
								
								src/drive.c
									
										
									
									
									
								
							
							
						
						
									
										486
									
								
								src/drive.c
									
										
									
									
									
								
							|  | @ -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; | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										122
									
								
								src/drive.h
									
										
									
									
									
								
							
							
						
						
									
										122
									
								
								src/drive.h
									
										
									
									
									
								
							|  | @ -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); | ||||
|  |  | |||
							
								
								
									
										770
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										770
									
								
								src/format.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -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
 | ||||
|  |  | |||
							
								
								
									
										30
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -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; | ||||
|  |  | |||
							
								
								
									
										15
									
								
								src/rufus.h
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/rufus.h
									
										
									
									
									
								
							|  | @ -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 | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -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" | ||||
|  |  | |||
|  | @ -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" | ||||
| 
 | ||||
|  |  | |||
|  | @ -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(); | ||||
| 	} | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
							
								
								
									
										15
									
								
								src/ui.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/ui.c
									
										
									
									
									
								
							|  | @ -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; | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue