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 "fat32.h" | ||||||
| #include "ntfs.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) | #if !defined(PARTITION_BASIC_DATA_GUID) | ||||||
| const GUID PARTITION_BASIC_DATA_GUID = | const GUID PARTITION_BASIC_DATA_GUID = | ||||||
| 	{ 0xebd0a0a2L, 0xb9e5, 0x4433, {0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7} }; | 	{ 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_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_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_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 | #endif | ||||||
| 
 | 
 | ||||||
| PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryVolumeInformationFile, (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS)); | 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; | RUFUS_DRIVE_INFO SelectedDrive; | ||||||
| BOOL installed_uefi_ntfs; | BOOL installed_uefi_ntfs; | ||||||
|  | DWORD partition_index[3]; | ||||||
| uint64_t persistence_size = 0; | 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) |  * 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; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	// Resolve a device path, so that we can look for that handle in case of access issues.
 | 	// 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, "???"); | 		strcpy(DevPath, "???"); | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < DRIVE_ACCESS_RETRIES; i++) { | 	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. |  * 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) |  * 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; | 	BOOL success = FALSE; | ||||||
| 	char partition_name[32]; | 	char partition_name[32]; | ||||||
| 
 | 
 | ||||||
| 	CheckDriveIndex(DriveIndex); | 	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; | 	success = TRUE; | ||||||
| out: | out: | ||||||
| 	return (success) ? safe_strdup(partition_name) : NULL; | 	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
 |  * 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; | 	static const char* ignore_device[] = { "\\Device\\CdRom", "\\Device\\Floppy" }; | ||||||
| 	char volume_name[MAX_PATH]; | 	static const char* volume_start = "\\\\?\\"; | ||||||
|  | 	char *ret = NULL, volume_name[MAX_PATH], path[MAX_PATH]; | ||||||
| 	HANDLE hDrive = INVALID_HANDLE_VALUE, hVolume = INVALID_HANDLE_VALUE; | 	HANDLE hDrive = INVALID_HANDLE_VALUE, hVolume = INVALID_HANDLE_VALUE; | ||||||
| 	size_t len; |  | ||||||
| 	char path[MAX_PATH]; |  | ||||||
| 	VOLUME_DISK_EXTENTS_REDEF DiskExtents; | 	VOLUME_DISK_EXTENTS_REDEF DiskExtents; | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 	UINT drive_type; | 	UINT drive_type; | ||||||
| 	int i, j; | 	StrArray found_name; | ||||||
| 	static const char* ignore_device[] = { "\\Device\\CdRom", "\\Device\\Floppy" }; | 	uint64_t found_offset[MAX_PARTITIONS] = { 0 }; | ||||||
| 	static const char* volume_start = "\\\\?\\"; | 	uint32_t i, j, k; | ||||||
|  | 	size_t len; | ||||||
| 
 | 
 | ||||||
|  | 	StrArrayCreate(&found_name, MAX_PARTITIONS); | ||||||
| 	CheckDriveIndex(DriveIndex); | 	CheckDriveIndex(DriveIndex); | ||||||
|  | 	if (PartitionIndex > MAX_PARTITIONS) | ||||||
|  | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; hDrive == INVALID_HANDLE_VALUE; i++) { | 	for (i = 0; hDrive == INVALID_HANDLE_VALUE; i++) { | ||||||
| 		if (i == 0) { | 		if (i == 0) { | ||||||
|  | @ -295,7 +313,7 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent | ||||||
| 				if (GetLastError() != ERROR_NO_MORE_FILES) { | 				if (GetLastError() != ERROR_NO_MORE_FILES) { | ||||||
| 					suprintf("Could not access next GUID volume: %s", WindowsErrorString()); | 					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; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		safe_closehandle(hDrive); | 		safe_closehandle(hDrive); | ||||||
| 		if ((DiskExtents.NumberOfDiskExtents >= 1) && (DiskExtents.Extents[0].DiskNumber == DriveIndex)) { | 		if (DiskExtents.NumberOfDiskExtents == 0) { | ||||||
| 			if (bKeepTrailingBackslash) | 			suprintf("Ignoring volume '%s' because it has no extents...", volume_name); | ||||||
| 				volume_name[len-1] = '\\'; | 			continue; | ||||||
| 			success = TRUE; | 		} | ||||||
|  | 		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; | 			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: | out: | ||||||
| 	if (hVolume != INVALID_HANDLE_VALUE) | 	if (hVolume != INVALID_HANDLE_VALUE) | ||||||
| 		FindVolumeClose(hVolume); | 		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, | 	hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, | ||||||
| 		&IID_IVdsServiceLoader, (void **)&pLoader); | 		&IID_IVdsServiceLoader, (void **)&pLoader); | ||||||
| 	if (hr != S_OK) { | 	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; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -386,14 +455,16 @@ BOOL DeletePartitions(DWORD DriveIndex) | ||||||
| 	hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService); | 	hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService); | ||||||
| 	IVdsServiceLoader_Release(pLoader); | 	IVdsServiceLoader_Release(pLoader); | ||||||
| 	if (hr != S_OK) { | 	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; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Query the VDS Service Providers
 | 	// Query the VDS Service Providers
 | ||||||
| 	hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum); | 	hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum); | ||||||
| 	if (hr != S_OK) { | 	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; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -407,7 +478,8 @@ BOOL DeletePartitions(DWORD DriveIndex) | ||||||
| 		hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider); | 		hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider); | ||||||
| 		IUnknown_Release(pUnk); | 		IUnknown_Release(pUnk); | ||||||
| 		if (hr != S_OK) { | 		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; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -415,7 +487,8 @@ BOOL DeletePartitions(DWORD DriveIndex) | ||||||
| 		hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider); | 		hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider); | ||||||
| 		IVdsProvider_Release(pProvider); | 		IVdsProvider_Release(pProvider); | ||||||
| 		if (hr != S_OK) { | 		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; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -423,7 +496,8 @@ BOOL DeletePartitions(DWORD DriveIndex) | ||||||
| 		hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack); | 		hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack); | ||||||
| 		IVdsSwProvider_Release(pSwProvider); | 		IVdsSwProvider_Release(pSwProvider); | ||||||
| 		if (hr != S_OK) { | 		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; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -436,14 +510,16 @@ BOOL DeletePartitions(DWORD DriveIndex) | ||||||
| 			hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack); | 			hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack); | ||||||
| 			IUnknown_Release(pPackUnk); | 			IUnknown_Release(pPackUnk); | ||||||
| 			if (hr != S_OK) { | 			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; | 				goto out; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			// Use the pack interface to access the disks
 | 			// Use the pack interface to access the disks
 | ||||||
| 			hr = IVdsPack_QueryDisks(pPack, &pEnumDisk); | 			hr = IVdsPack_QueryDisks(pPack, &pEnumDisk); | ||||||
| 			if (hr != S_OK) { | 			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; | 				goto out; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -458,14 +534,16 @@ BOOL DeletePartitions(DWORD DriveIndex) | ||||||
| 				// Get the disk interface.
 | 				// Get the disk interface.
 | ||||||
| 				hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk); | 				hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk); | ||||||
| 				if (hr != S_OK) { | 				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; | 					goto out; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				// Get the disk properties
 | 				// Get the disk properties
 | ||||||
| 				hr = IVdsDisk_GetProperties(pDisk, &diskprop); | 				hr = IVdsDisk_GetProperties(pDisk, &diskprop); | ||||||
| 				if (hr != S_OK) { | 				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; | 					goto out; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  | @ -479,65 +557,58 @@ BOOL DeletePartitions(DWORD DriveIndex) | ||||||
| 				hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk); | 				hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk); | ||||||
| 				IVdsDisk_Release(pDisk); | 				IVdsDisk_Release(pDisk); | ||||||
| 				if (hr != S_OK) { | 				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; | 					goto out; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				// Query the partition data, so we can get the start offset, which we need for deletion
 | 				// 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); | 				hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size); | ||||||
| 				if (hr != S_OK) { | 				if (hr == S_OK) { | ||||||
| 					uprintf("No partition to delete on disk '%ws'", diskprop.pwszName); | 					uprintf("Deleting ALL partition(s) from disk '%S':", diskprop.pwszName); | ||||||
| 					goto out; | 					// Now go through each partition
 | ||||||
| 				} | 					for (i = 0; i < prop_array_size; i++) { | ||||||
| 
 | 						uprintf("● Partition %d (offset: %lld, size: %s)", prop_array[i].ulPartitionNumber, | ||||||
| 				uprintf("Deleting ALL partitions from disk '%ws':", diskprop.pwszName); | 							prop_array[i].ullOffset, SizeToHumanReadable(prop_array[i].ullSize, FALSE, FALSE)); | ||||||
| 
 | 						hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE); | ||||||
| 				// Now go through each partition
 | 						if (hr != S_OK) { | ||||||
| 				r = (prop_array_size >= 1); | 							r = FALSE; | ||||||
| 				for (i = 0; i < prop_array_size; i++) { | 							VDS_SET_ERROR(hr); | ||||||
| 					uprintf("● Partition %d (offset: %lld, size: %s)", prop_array[i].ulPartitionNumber, | 							uprintf("Could not delete partitions: %s", WindowsErrorString()); | ||||||
| 						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); |  | ||||||
| 					} | 					} | ||||||
|  | 					r = TRUE; | ||||||
|  | 				} else { | ||||||
|  | 					uprintf("No partition to delete on disk '%S'", diskprop.pwszName); | ||||||
|  | 					r = TRUE; | ||||||
| 				} | 				} | ||||||
| 				CoTaskMemFree(prop_array); | 				CoTaskMemFree(prop_array); | ||||||
| 
 | 
 | ||||||
| // NB: In the future, we could try something like this to format partitions:
 |  | ||||||
| #if 0 | #if 0 | ||||||
| 				// Initiate formatting and wait for completion.
 | 				// Issue a Clean while we're at it
 | ||||||
| 				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; |  | ||||||
| 				HRESULT hr2 = E_FAIL; | 				HRESULT hr2 = E_FAIL; | ||||||
| 				do { | 				ULONG completed; | ||||||
| 					hr = IVdsAsync_QueryStatus(pAsync, &hr2, &ulPercentCompleted); | 				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)) { | 					if (SUCCEEDED(hr)) { | ||||||
| 						printf("%ld%%", ulPercentCompleted); | 						hr = hr2; | ||||||
| 						if ((hr2 != S_OK) && (hr2 != VDS_E_OPERATION_PENDING)) { | 						if (hr == S_OK) | ||||||
| 							uprintf("hr2: %X", hr2); |  | ||||||
| 							break; | 							break; | ||||||
| 						} | 						if (hr == VDS_E_OPERATION_PENDING) | ||||||
| 						if (hr2 == S_OK) { | 							hr = S_OK; | ||||||
| 							break; |  | ||||||
| 						} |  | ||||||
| 					} | 					} | ||||||
| 					Sleep(500); | 					Sleep(500); | ||||||
| 				} while (SUCCEEDED(hr)); | 				} | ||||||
| 				hr = IVdsAsync_Wait(pAsync, &hr2, &AsyncOut); | 				if (hr != S_OK) { | ||||||
| 				IVdsAsync_Release(pAsync); | 					VDS_SET_ERROR(hr); | ||||||
|  | 					uprintf("Could not clean disk: %s", WindowsErrorString()); | ||||||
|  | 				} | ||||||
| #endif | #endif | ||||||
| 				IVdsAdvancedDisk_Release(pAdvancedDisk); | 				IVdsAdvancedDisk_Release(pAdvancedDisk); | ||||||
| 				goto out; | 				goto out; | ||||||
|  | @ -551,7 +622,7 @@ out: | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Wait for a logical drive to reappear - Used when a drive has just been repartitioned */ | /* 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; | 	uint64_t EndTime; | ||||||
| 	char* LogicalPath = NULL; | 	char* LogicalPath = NULL; | ||||||
|  | @ -560,11 +631,13 @@ BOOL WaitForLogical(DWORD DriveIndex) | ||||||
| 	// make sure we don't spend more than DRIVE_ACCESS_TIMEOUT in wait.
 | 	// make sure we don't spend more than DRIVE_ACCESS_TIMEOUT in wait.
 | ||||||
| 	EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT; | 	EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT; | ||||||
| 	do { | 	do { | ||||||
| 		LogicalPath = GetLogicalName(DriveIndex, FALSE, TRUE); | 		LogicalPath = GetLogicalName(DriveIndex, PartitionIndex, FALSE, TRUE); | ||||||
| 		if (LogicalPath != NULL) { | 		// 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); | 			free(LogicalPath); | ||||||
| 			return TRUE; | 			return TRUE; | ||||||
| 		} | 		} | ||||||
|  | 		free(LogicalPath); | ||||||
| 		if (IS_ERROR(FormatStatus))	// User cancel
 | 		if (IS_ERROR(FormatStatus))	// User cancel
 | ||||||
| 			return FALSE; | 			return FALSE; | ||||||
| 		Sleep(DRIVE_ACCESS_TIMEOUT/DRIVE_ACCESS_RETRIES); | 		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 |  * Returns INVALID_HANDLE_VALUE on error or NULL if no logical path exists (typical | ||||||
|  * of unpartitioned drives) |  * 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; | 	HANDLE hLogical = INVALID_HANDLE_VALUE; | ||||||
| 	char* LogicalPath = GetLogicalName(DriveIndex, FALSE, FALSE); | 	char* LogicalPath = GetLogicalName(DriveIndex, PartitionIndex, FALSE, FALSE); | ||||||
| 
 | 
 | ||||||
| 	if (LogicalPath == NULL) { | 	if (LogicalPath == NULL) { | ||||||
| 		uprintf("No logical drive found (unpartitioned?)"); | 		uprintf("No logical drive found (unpartitioned?)"); | ||||||
|  | @ -956,7 +1029,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys | ||||||
| 	SelectedDrive.nPartitions = 0; | 	SelectedDrive.nPartitions = 0; | ||||||
| 	// Populate the filesystem data
 | 	// Populate the filesystem data
 | ||||||
| 	FileSystemName[0] = 0; | 	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))) { | 	if ((volume_name == NULL) || (!GetVolumeInformationA(volume_name, NULL, 0, NULL, NULL, NULL, FileSystemName, FileSystemNameSize))) { | ||||||
| 		suprintf("No volume information for drive 0x%02x", DriveIndex); | 		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. |  * Mount the volume identified by drive_guid to mountpoint drive_name. | ||||||
|  * If drive_guid is already mounted, but with a different letter than the |  * If volume_name is already mounted, but with a different letter than the | ||||||
|  * one requested, drive_name is updated to use that letter. |  * 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_guid[52]; | ||||||
| 	char mounted_letter[27] = { 0 }; | 	char mounted_letter[27] = { 0 }; | ||||||
| 	DWORD size; | 	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; | 		return FALSE; | ||||||
| 
 | 
 | ||||||
| 	// Windows may already have the volume mounted but under a different letter.
 | 	// Windows may already have the volume mounted but under a different letter.
 | ||||||
| 	// If that is the case, update drive_name to that 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]) ) { | 	  && (size > 1) && (mounted_letter[0] != drive_name[0]) ) { | ||||||
| 		uprintf("%s is already mounted as %C: instead of %C: - Will now use this target instead...", | 		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]; | 		drive_name[0] = mounted_letter[0]; | ||||||
| 		return TRUE; | 		return TRUE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!SetVolumeMountPointA(drive_name, drive_guid)) { | 	if (!SetVolumeMountPointA(drive_name, volume_name)) { | ||||||
| 		if (GetLastError() == ERROR_DIR_NOT_EMPTY) { | 		if (GetLastError() == ERROR_DIR_NOT_EMPTY) { | ||||||
| 			if (!GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid))) { | 			if (!GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid))) { | ||||||
| 				uprintf("%s is already mounted, but volume GUID could not be checked: %s", | 				uprintf("%s is already mounted, but volume GUID could not be checked: %s", | ||||||
| 					drive_name, WindowsErrorString()); | 					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", | 				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 { | 			} 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; | 				return TRUE; | ||||||
| 			} | 			} | ||||||
| 			uprintf("Retrying after dismount..."); | 			uprintf("Retrying after dismount..."); | ||||||
| 			if (!DeleteVolumeMountPointA(drive_name)) | 			if (!DeleteVolumeMountPointA(drive_name)) | ||||||
| 				uprintf("Warning: Could not delete volume mountpoint: %s", WindowsErrorString()); | 				uprintf("Warning: Could not delete volume mountpoint: %s", WindowsErrorString()); | ||||||
| 			if (SetVolumeMountPointA(drive_name, drive_guid)) | 			if (SetVolumeMountPointA(drive_name, volume_name)) | ||||||
| 				return TRUE; | 				return TRUE; | ||||||
| 			if ((GetLastError() == ERROR_DIR_NOT_EMPTY) && | 			if ((GetLastError() == ERROR_DIR_NOT_EMPTY) && | ||||||
| 				GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid)) && | 				GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid)) && | ||||||
| 				(safe_strcmp(drive_guid, mounted_guid) == 0)) { | 				(safe_strcmp(volume_name, mounted_guid) == 0)) { | ||||||
| 				uprintf("%s was remounted as %C: (second time lucky!)", drive_guid, drive_name[0]); | 				uprintf("%s was remounted as %C: (second time lucky!)", volume_name, drive_name[0]); | ||||||
| 				return TRUE; | 				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 |  * Alternate version of MountVolume required for ESP's, since Windows (including VDS) does | ||||||
|  * drive letter. Returns the newly allocated drive string. |  * *NOT* provide any means of mounting these volume but through DefineDosDevice(). Also | ||||||
|  * We need to do this because, for instance, EFI System partitions are not assigned |  * note the bcdboot is very finicky about what it may or may not handle, even if the | ||||||
|  * Volume GUIDs by the OS, and we need to have a letter assigned, for when we invoke |  * mount was successful (e.g. '\Device\HarddiskVolume###' vs 'Device\HarddiskVolume###'). | ||||||
|  * bcdtool for Windows To Go. All in all, the process looks like this: |  * Returned string is static (no concurrency) and should not be freed. | ||||||
|  * 1. F: = \Device\HarddiskVolume9 (SINGLE LOOKUP) |  | ||||||
|  * 2. Harddisk5Partition1 = \Device\HarddiskVolume9 (FULL LOOKUP) |  | ||||||
|  * 3. Harddisk5Partition2 = \Device\HarddiskVolume10 (SINGLE LOOKUP) |  | ||||||
|  * 4. DefineDosDevice(letter, \Device\HarddiskVolume10) |  | ||||||
|  */ |  */ | ||||||
| char* AltMountVolume(const char* drive_name, uint8_t part_nr) | char* AltMountVolume(DWORD DriveIndex, DWORD PartitionIndex) | ||||||
| { | { | ||||||
|  | 	char* ret = NULL, *volume_name = NULL; | ||||||
| 	static char mounted_drive[] = "?:"; | 	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(); | 	mounted_drive[0] = GetUnusedDriveLetter(); | ||||||
| 	if (mounted_drive[0] == 0) { | 	if (mounted_drive[0] == 0) { | ||||||
| 		uprintf("Could not find an unused drive letter"); | 		uprintf("Could not find an unused drive letter"); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 	volume_name = GetLogicalName(DriveIndex, PartitionIndex, FALSE, TRUE); | ||||||
| 	target[0][0] = 0; | 	if ((volume_name == NULL) || (strncmp(volume_name, groot_name, groot_len) != 0)) { | ||||||
| 	// Convert our drive letter to something like "\Device\HarddiskVolume9"
 | 		uprintf("Unexpected volume name: '%s'", volume_name); | ||||||
| 	if (!QueryDosDeviceA(drive_name, target[0], MAX_PATH) || (strlen(target[0]) == 0)) { |  | ||||||
| 		uprintf("Could not get the DOS volume name for '%s': %s", drive_name, WindowsErrorString()); |  | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Now parse the whole DOS device list to find the 'Harddisk#Partition#' that matches the above
 | 	// bcdboot sure won't like it if you forget the starting '\'
 | ||||||
| 	// TODO: realloc if someone ever manages to burst through 64K of DOS devices
 | 	if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH | DDD_NO_BROADCAST_SYSTEM, mounted_drive, &volume_name[14])) { | ||||||
| 	buffer = malloc(bufsize); | 		uprintf("Could not mount '%s' to '%s': %s", &volume_name[14], mounted_drive, WindowsErrorString()); | ||||||
| 	if (buffer == NULL) |  | ||||||
| 		goto out; |  | ||||||
| 
 |  | ||||||
| 	buffer[0] = 0; |  | ||||||
| 	if (!QueryDosDeviceA(NULL, buffer, bufsize)) { |  | ||||||
| 		uprintf("Could not get the DOS device list: %s", WindowsErrorString()); |  | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	p = buffer; | 	uprintf("Successfully mounted '%s' (Partition %d) as '%s'", &volume_name[14], PartitionIndex, mounted_drive); | ||||||
| 	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); |  | ||||||
| 	ret = mounted_drive; | 	ret = mounted_drive; | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	safe_free(buffer); | 	free(volume_name); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1297,23 +1325,23 @@ BOOL AltUnmountVolume(const char* drive_name) | ||||||
|  */ |  */ | ||||||
| BOOL RemountVolume(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
 | 	// UDF requires a sync/flush, and it's also a good idea for other FS's
 | ||||||
| 	FlushDrive(drive_name[0]); | 	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)) { | 		if (DeleteVolumeMountPointA(drive_name)) { | ||||||
| 			Sleep(200); | 			Sleep(200); | ||||||
| 			if (MountVolume(drive_name, drive_guid)) { | 			if (MountVolume(drive_name, volume_name)) { | ||||||
| 				uprintf("Successfully remounted %s as %C:", drive_guid, drive_name[0]); | 				uprintf("Successfully remounted %s as %C:", volume_name, drive_name[0]); | ||||||
| 			} else { | 			} 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
 | 				// 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); | 				FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_REMOUNT_VOLUME); | ||||||
| 				return FALSE; | 				return FALSE; | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} 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
 | 			// Try to continue regardless
 | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1328,7 +1356,7 @@ typedef struct _DRIVE_LAYOUT_INFORMATION_EX4 { | ||||||
| 		DRIVE_LAYOUT_INFORMATION_MBR Mbr; | 		DRIVE_LAYOUT_INFORMATION_MBR Mbr; | ||||||
| 		DRIVE_LAYOUT_INFORMATION_GPT Gpt; | 		DRIVE_LAYOUT_INFORMATION_GPT Gpt; | ||||||
| 	} Type; | 	} Type; | ||||||
| 	PARTITION_INFORMATION_EX PartitionEntry[4]; | 	PARTITION_INFORMATION_EX PartitionEntry[MAX_PARTITIONS]; | ||||||
| } DRIVE_LAYOUT_INFORMATION_EX4,*PDRIVE_LAYOUT_INFORMATION_EX4; | } 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) | 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 char* PartitionTypeName[] = { "MBR", "GPT", "SFD" }; | ||||||
|  | 	const wchar_t* extra_part_name; | ||||||
| 	unsigned char* buffer; | 	unsigned char* buffer; | ||||||
| 	size_t uefi_ntfs_size = 0; | 	size_t uefi_ntfs_size = 0; | ||||||
| 	CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}}; | 	CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}}; | ||||||
| 	DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0}; | 	DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0}; | ||||||
| 	BOOL r; | 	BOOL r; | ||||||
| 	DWORD i, size, bufsize, pn = 0; | 	DWORD i, size, bufsize, pn = 0; | ||||||
| 	LONGLONG main_part_size_in_sectors, extra_part_size_in_tracks = 0, 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; | 	const LONGLONG bytes_per_track = ((LONGLONG)SelectedDrive.SectorsPerTrack) * SelectedDrive.SectorSize; | ||||||
| 
 | 
 | ||||||
| 	PrintInfoDebug(0, MSG_238, PartitionTypeName[partition_style]); | 	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) | 		if (uefi_ntfs_size == 0) | ||||||
| 			return FALSE; | 			return FALSE; | ||||||
| 	} | 	} | ||||||
|  | 	memset(partition_index, 0, sizeof(partition_index)); | ||||||
| 
 | 
 | ||||||
| 	// Compute the start offset of our first partition
 | 	// Compute the start offset of our first partition
 | ||||||
| 	if ((partition_style == PARTITION_STYLE_GPT) || (!IsChecked(IDC_OLD_BIOS_FIXES))) { | 	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; | 		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 required, set the MSR partition (GPT only - must be created before the data part)
 | ||||||
| 	if ((partition_style == PARTITION_STYLE_GPT) && (extra_partitions & XP_MSR)) { | 	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].PartitionLength.QuadPart = 128*MB; | ||||||
| 		DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_MSFT_RESERVED_GUID; | 		DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_MSFT_RESERVED_GUID; | ||||||
| 		IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId)); | 		IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId)); | ||||||
| 		// coverity[strcpy_overrun]
 | 		// 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
 | 		// 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)) { | 		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); | 				free(buffer); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		pn++; | 		pn++; | ||||||
| 		DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart + | 		DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart + | ||||||
| 				DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart; | 				DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart; | ||||||
| 	} | 	} | ||||||
|  | 	// Clear the extra partitions we processed
 | ||||||
|  | 	extra_partitions &= ~(XP_ESP|XP_MSR); | ||||||
| 
 | 
 | ||||||
| 	// Set our main data partition
 | 	// Set our main data partition
 | ||||||
| 	main_part_size_in_sectors = (SelectedDrive.DiskSize - DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart) / | 	main_part_size_in_sectors = (SelectedDrive.DiskSize - DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart) / | ||||||
| 		// Need 33 sectors at the end for secondary GPT
 | 		// Need 33 sectors at the end for secondary GPT
 | ||||||
| 		SelectedDrive.SectorSize - ((partition_style == PARTITION_STYLE_GPT)?33:0); | 		SelectedDrive.SectorSize - ((partition_style == PARTITION_STYLE_GPT)?33:0); | ||||||
| 	if (main_part_size_in_sectors <= 0) | 	if (!extra_partitions) { | ||||||
| 		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)); | ||||||
| 	// Adjust the size according to extra partitions (which we always align to a track)
 | 	} else { | ||||||
| 	if (extra_partitions) { | 		// Adjust the size according to extra partitions (which we always align to a track)
 | ||||||
| 		uprintf("Adding %s partition", (extra_partitions & XP_CASPER) ? "casper-rw": "extra"); | 		if (extra_partitions & XP_UEFI_NTFS) { | ||||||
| 		if (extra_partitions & XP_EFI) { | 			extra_part_name = L"UEFI:NTFS"; | ||||||
| 			// 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) { |  | ||||||
| 			extra_part_size_in_tracks = (max(MIN_EXTRA_PART_SIZE, uefi_ntfs_size) + bytes_per_track - 1) / bytes_per_track; | 			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)) { | 		} else if ((extra_partitions & XP_CASPER)) { | ||||||
| 			assert(persistence_size != 0); | 			assert(persistence_size != 0); | ||||||
|  | 			extra_part_name = L"Linux Persistence"; | ||||||
| 			extra_part_size_in_tracks = persistence_size / bytes_per_track; | 			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) - | 		main_part_size_in_sectors = ((main_part_size_in_sectors / SelectedDrive.SectorsPerTrack) - | ||||||
| 			extra_part_size_in_tracks) * SelectedDrive.SectorsPerTrack; | 			extra_part_size_in_tracks) * SelectedDrive.SectorsPerTrack; | ||||||
| 		if (main_part_size_in_sectors <= 0) | 		uprintf("● Creating Main Data Partition: %lld tracks (%s)", main_part_size_in_sectors / SelectedDrive.SectorsPerTrack, | ||||||
| 			return FALSE; | 			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; | 	DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = main_part_size_in_sectors * SelectedDrive.SectorSize; | ||||||
| 	if (partition_style == PARTITION_STYLE_MBR) { | 	if (partition_style == PARTITION_STYLE_MBR) { | ||||||
| 		DriveLayoutEx.PartitionEntry[pn].Mbr.BootIndicator = (boot_type != BT_NON_BOOTABLE); | 		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: | 		case FS_REFS: | ||||||
| 			DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x07; | 			DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x07; | ||||||
| 			break; | 			break; | ||||||
|  | 		case FS_EXT2: | ||||||
|  | 		case FS_EXT3: | ||||||
|  | 		case FS_EXT4: | ||||||
|  | 			DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x83; | ||||||
|  | 			break; | ||||||
| 		case FS_FAT32: | 		case FS_FAT32: | ||||||
| 			DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x0c;	// FAT32 LBA
 | 			DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x0c;	// FAT32 LBA
 | ||||||
| 			break; | 			break; | ||||||
|  | @ -1456,61 +1516,49 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m | ||||||
| 	} else { | 	} else { | ||||||
| 		DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_BASIC_DATA_GUID; | 		DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_BASIC_DATA_GUID; | ||||||
| 		IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId)); | 		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++; | 	pn++; | ||||||
|  | 	partition_index[PI_MAIN] = pn; | ||||||
| 
 | 
 | ||||||
| 	// Set the optional extra partition
 | 	// Set the optional extra partition
 | ||||||
| 	if (extra_partitions) { | 	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
 | 		// Should end on a track boundary
 | ||||||
| 		DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart + | 		DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart + | ||||||
| 			DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart; | 			DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart; | ||||||
| 		DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = (extra_partitions & XP_UEFI_NTFS)?uefi_ntfs_size: | 		DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = (extra_partitions & XP_UEFI_NTFS)?uefi_ntfs_size: | ||||||
| 			extra_part_size_in_tracks * bytes_per_track; | 			extra_part_size_in_tracks * bytes_per_track; | ||||||
| 		if (partition_style == PARTITION_STYLE_GPT) { | 		if (partition_style == PARTITION_STYLE_GPT) { | ||||||
| 			const wchar_t* name = L"Basic Data"; | 			DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_BASIC_DATA_GUID; | ||||||
| 			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; |  | ||||||
| 			IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId)); | 			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 { | 		} else { | ||||||
| 			BYTE type = 0; |  | ||||||
| 			if (extra_partitions & XP_UEFI_NTFS) { | 			if (extra_partitions & XP_UEFI_NTFS) { | ||||||
| 				type = 0xef; | 				DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0xef; | ||||||
| 			} else if (extra_partitions & XP_CASPER) { | 			} else if (extra_partitions & XP_CASPER) { | ||||||
| 				type = 0x83; | 				DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x83; | ||||||
| 			}  else if (extra_partitions & XP_COMPAT) { | 			}  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
 | 				// Set the one track compatibility partition to be all hidden sectors
 | ||||||
| 				DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.SectorsPerTrack; | 				DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.SectorsPerTrack; | ||||||
| 			} else { | 			} else { | ||||||
| 				assert(FALSE); | 				assert(FALSE); | ||||||
| 			} | 			} | ||||||
| 			DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = type; |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// We need to write the UEFI:NTFS partition before we refresh the disk
 | 		// We need to write the UEFI:NTFS partition before we refresh the disk
 | ||||||
| 		if (extra_partitions & XP_UEFI_NTFS) { | 		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)) { | 			if (!SetFilePointerEx(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, NULL, FILE_BEGIN)) { | ||||||
| 				uprintf("Unable to set position"); | 				uprintf("Could not set position"); | ||||||
| 				return FALSE; | 				return FALSE; | ||||||
| 			} | 			} | ||||||
| 			buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_NTFS), _RT_RCDATA, "uefi-ntfs.img", &bufsize, FALSE); | 			buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_NTFS), _RT_RCDATA, "uefi-ntfs.img", &bufsize, FALSE); | ||||||
| 			if (buffer == NULL) { | 			if (buffer == NULL) { | ||||||
| 				uprintf("Could not access uefi-ntfs.img"); | 				uprintf("Could not access source image"); | ||||||
| 				return FALSE; | 				return FALSE; | ||||||
| 			} | 			} | ||||||
| 			if(!WriteFileWithRetry(hDrive, buffer, bufsize, &size, WRITE_RETRIES)) { | 			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
 | 	// Initialize the remaining partition data
 | ||||||
| 	for (i = 0; i < pn; i++) { | 	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].PartitionStyle = partition_style; | ||||||
| 		DriveLayoutEx.PartitionEntry[i].RewritePartition = TRUE; | 		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; | 		CreateDisk.PartitionStyle = PARTITION_STYLE_GPT; | ||||||
| 		IGNORE_RETVAL(CoCreateGuid(&CreateDisk.Gpt.DiskId)); | 		IGNORE_RETVAL(CoCreateGuid(&CreateDisk.Gpt.DiskId)); | ||||||
| 		CreateDisk.Gpt.MaxPartitionCount = MAX_GPT_PARTITIONS; | 		CreateDisk.Gpt.MaxPartitionCount = MAX_PARTITIONS; | ||||||
| 
 | 
 | ||||||
| 		DriveLayoutEx.PartitionStyle = PARTITION_STYLE_GPT; | 		DriveLayoutEx.PartitionStyle = PARTITION_STYLE_GPT; | ||||||
| 		DriveLayoutEx.PartitionCount = pn; | 		DriveLayoutEx.PartitionCount = pn; | ||||||
| 		// At the very least, a GPT disk has 34 reserved sectors at the beginning and 33 at the end.
 | 		// 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.StartingUsableOffset.QuadPart = 34 * SelectedDrive.SectorSize; | ||||||
| 		DriveLayoutEx.Type.Gpt.UsableLength.QuadPart = SelectedDrive.DiskSize - (34+33) * 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; | 		DriveLayoutEx.Type.Gpt.DiskId = CreateDisk.Gpt.DiskId; | ||||||
| 		break; | 		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) | 	CTL_CODE(MOUNTMGRCONTROLTYPE, 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) | ||||||
| 
 | 
 | ||||||
| #define XP_MSR                              0x01 | #define XP_MSR                              0x01 | ||||||
| #define XP_EFI                              0x02 | #define XP_ESP                              0x02 | ||||||
| #define XP_UEFI_NTFS                        0x04 | #define XP_UEFI_NTFS                        0x04 | ||||||
| #define XP_COMPAT                           0x08 | #define XP_COMPAT                           0x08 | ||||||
| #define XP_CASPER                           0x10 | #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 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__) | #if !defined(__MINGW32__) | ||||||
| typedef enum _FSINFOCLASS { | typedef enum _FSINFOCLASS { | ||||||
| 	FileFsVolumeInformation = 1, | 	FileFsVolumeInformation = 1, | ||||||
|  | @ -87,6 +101,25 @@ typedef interface IVdsDisk IVdsDisk; | ||||||
| typedef interface IVdsAdvancedDisk IVdsAdvancedDisk; | typedef interface IVdsAdvancedDisk IVdsAdvancedDisk; | ||||||
| typedef interface IVdsAdviseSink IVdsAdviseSink; | typedef interface IVdsAdviseSink IVdsAdviseSink; | ||||||
| typedef interface IVdsAsync IVdsAsync; | 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 { | typedef struct IVdsServiceLoaderVtbl { | ||||||
| 	HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsServiceLoader *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject); | 	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; | 	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 IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This) | ||||||
| #define IVdsService_QueryProviders(This,masks,ppEnum) (This)->lpVtbl->QueryProviders(This,masks,ppEnum) | #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 IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject) | ||||||
| #define IVdsProvider_Release(This) (This)->lpVtbl->Release(This) | #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 IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This) | ||||||
| #define IVdsPack_QueryDisks(This,ppEnum) (This)->lpVtbl->QueryDisks(This,ppEnum) | #define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum) | ||||||
| #define IVdsDisk_GetProperties(This,pDiskProperties) (This)->lpVtbl->GetProperties(This,pDiskProperties) | #define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties) | ||||||
| #define IVdsDisk_Release(This) (This)->lpVtbl->Release(This) | #define IVdsDisk_Release(This) (This)->lpVtbl->Release(This) | ||||||
| #define IVdsDisk_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) | #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_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_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 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 | #endif | ||||||
| 
 | 
 | ||||||
| static __inline BOOL UnlockDrive(HANDLE hDrive) { | static __inline BOOL UnlockDrive(HANDLE hDrive) { | ||||||
|  | @ -256,16 +345,17 @@ typedef struct { | ||||||
| } RUFUS_DRIVE_INFO; | } RUFUS_DRIVE_INFO; | ||||||
| extern RUFUS_DRIVE_INFO SelectedDrive; | extern RUFUS_DRIVE_INFO SelectedDrive; | ||||||
| extern uint64_t persistence_size; | extern uint64_t persistence_size; | ||||||
|  | extern DWORD partition_index[3]; | ||||||
| 
 | 
 | ||||||
| BOOL SetAutoMount(BOOL enable); | BOOL SetAutoMount(BOOL enable); | ||||||
| BOOL GetAutoMount(BOOL* enabled); | BOOL GetAutoMount(BOOL* enabled); | ||||||
| char* GetPhysicalName(DWORD DriveIndex); | char* GetPhysicalName(DWORD DriveIndex); | ||||||
| char* GetPartitionName(DWORD DriveIndex, DWORD PartitionNumber); | char* GetPartitionName(DWORD DriveIndex, DWORD PartitionIndex); | ||||||
| BOOL DeletePartitions(DWORD DriveIndex); | BOOL DeletePartitions(DWORD DriveIndex); | ||||||
| HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare); | HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare); | ||||||
| char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent); | char* GetLogicalName(DWORD DriveIndex, DWORD PartitionIndex, BOOL bKeepTrailingBackslash, BOOL bSilent); | ||||||
| BOOL WaitForLogical(DWORD DriveIndex); | BOOL WaitForLogical(DWORD DriveIndex, DWORD PartitionIndex); | ||||||
| HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare); | HANDLE GetLogicalHandle(DWORD DriveIndex, DWORD PartitionIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare); | ||||||
| int GetDriveNumber(HANDLE hDrive, char* path); | int GetDriveNumber(HANDLE hDrive, char* path); | ||||||
| BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters); | BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters); | ||||||
| UINT GetDriveTypeFromIndex(DWORD DriveIndex); | UINT GetDriveTypeFromIndex(DWORD DriveIndex); | ||||||
|  | @ -279,7 +369,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys | ||||||
| BOOL UnmountVolume(HANDLE hDrive); | BOOL UnmountVolume(HANDLE hDrive); | ||||||
| BOOL MountVolume(char* drive_name, char *drive_guid); | BOOL MountVolume(char* drive_name, char *drive_guid); | ||||||
| BOOL AltUnmountVolume(const char* drive_name); | 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 RemountVolume(char* drive_name); | ||||||
| BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, uint8_t extra_partitions); | BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, uint8_t extra_partitions); | ||||||
| BOOL InitializeDisk(HANDLE hDrive); | 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; | 	int size = 0; | ||||||
| 	char* str = NULL; | 	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
 | 	// Find out the size we need to allocate for our converted string
 | ||||||
| 	size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); | 	size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); | ||||||
| 	if (size <= 1)	// An empty string would be size 1
 | 	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) | 	if (str == NULL) | ||||||
| 		return 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
 | 	// Find out the size we need to allocate for our converted string
 | ||||||
| 	size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); | 	size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); | ||||||
| 	if (size <= 1)	// An empty string would be size 1
 | 	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" | #include "../res/grub2/grub2_version.h" | ||||||
| 
 | 
 | ||||||
| static const char* cmdline_hogger = "rufus.com"; | 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* ep_reg = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"; | ||||||
| static const char* vs_reg = "Software\\Microsoft\\VisualStudio"; | static const char* vs_reg = "Software\\Microsoft\\VisualStudio"; | ||||||
| static BOOL existing_key = FALSE;	// For LGP set/restore
 | static BOOL existing_key = FALSE;	// For LGP set/restore
 | ||||||
|  | @ -84,6 +83,7 @@ extern long grub2_len; | ||||||
| extern char* szStatusMessage; | extern char* szStatusMessage; | ||||||
| extern const char* old_c32_name[NB_OLD_C32]; | extern const char* old_c32_name[NB_OLD_C32]; | ||||||
| extern const char* cert_name[3]; | extern const char* cert_name[3]; | ||||||
|  | extern const char* FileSystemLabel[FS_MAX]; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Globals |  * 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 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 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 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; | float fScale = 1.0f; | ||||||
| int dialog_showing = 0, selection_default = BT_IMAGE, windows_to_go_selection = 0, persistence_unit_selection = -1; | 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
 | 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; | char image_option_txt[128], *fido_url = NULL; | ||||||
| StrArray DriveID, DriveLabel, DriveHub, BlockingProcess, ImageList; | StrArray DriveID, DriveLabel, DriveHub, BlockingProcess, ImageList; | ||||||
| // Number of steps for each FS for FCC_STRUCTURE_PROGRESS
 | // 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" }; | const char* flash_type[BADLOCKS_PATTERN_TYPES] = { "SLC", "MLC", "TLC" }; | ||||||
| 
 | 
 | ||||||
| // TODO: Remember to update copyright year in stdlg's AboutCallback() WM_INITDIALOG,
 | // TODO: Remember to update copyright year in stdlg's AboutCallback() WM_INITDIALOG,
 | ||||||
|  | @ -1859,10 +1859,6 @@ out: | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #ifdef RUFUS_TEST |  | ||||||
| extern BOOL FormatExtFs(const char* label, uint32_t version); |  | ||||||
| #endif |  | ||||||
| /*
 | /*
 | ||||||
|  * Main dialog callback |  * Main dialog callback | ||||||
|  */ |  */ | ||||||
|  | @ -1898,7 +1894,15 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 	case WM_COMMAND: | 	case WM_COMMAND: | ||||||
| #ifdef RUFUS_TEST | #ifdef RUFUS_TEST | ||||||
| 		if (LOWORD(wParam) == IDC_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; | 			break; | ||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
|  | @ -3026,6 +3030,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 	advanced_mode_format = ReadSettingBool(SETTING_ADVANCED_MODE_FORMAT); | 	advanced_mode_format = ReadSettingBool(SETTING_ADVANCED_MODE_FORMAT); | ||||||
| 	preserve_timestamps = ReadSettingBool(SETTING_PRESERVE_TIMESTAMPS); | 	preserve_timestamps = ReadSettingBool(SETTING_PRESERVE_TIMESTAMPS); | ||||||
| 	use_fake_units = !ReadSettingBool(SETTING_USE_PROPER_SIZE_UNITS); | 	use_fake_units = !ReadSettingBool(SETTING_USE_PROPER_SIZE_UNITS); | ||||||
|  | 	use_vds = ReadSettingBool(SETTING_USE_VDS); | ||||||
| 	usb_debug = ReadSettingBool(SETTING_ENABLE_USB_DEBUG); | 	usb_debug = ReadSettingBool(SETTING_ENABLE_USB_DEBUG); | ||||||
| 	detect_fakes = !ReadSettingBool(SETTING_DISABLE_FAKE_DRIVES_CHECK); | 	detect_fakes = !ReadSettingBool(SETTING_DISABLE_FAKE_DRIVES_CHECK); | ||||||
| 	allow_dual_uefi_bios = ReadSettingBool(SETTING_ENABLE_WIN_DUAL_EFI_BIOS); | 	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
 | 	// Do our own event processing and process "magic" commands
 | ||||||
| 	while(GetMessage(&msg, NULL, 0, 0)) { | 	while(GetMessage(&msg, NULL, 0, 0)) { | ||||||
| 		// ** *****  **** ** ***** ****
 | 		// ** *****  **** ** **********
 | ||||||
| 		// .,ABCDEFGHIJKLMNOPQRSTUVWXYZ
 | 		// .,ABCDEFGHIJKLMNOPQRSTUVWXYZ
 | ||||||
| 
 | 
 | ||||||
| 		// Ctrl-A => Select the log data
 | 		// Ctrl-A => Select the log data
 | ||||||
|  | @ -3357,6 +3362,13 @@ relaunch: | ||||||
| 			GetDevices(0); | 			GetDevices(0); | ||||||
| 			continue; | 			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
 | 		// Alt-W => Enable VMWare disk detection
 | ||||||
| 		if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'W')) { | 		if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'W')) { | ||||||
| 			enable_vmdk = !enable_vmdk; | 			enable_vmdk = !enable_vmdk; | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								src/rufus.h
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/rufus.h
									
										
									
									
									
								
							|  | @ -22,13 +22,16 @@ | ||||||
| #if defined(_MSC_VER) | #if defined(_MSC_VER) | ||||||
| // Disable some VS Code Analysis warnings
 | // Disable some VS Code Analysis warnings
 | ||||||
| #pragma warning(disable: 4996)		// Ignore deprecated
 | #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: 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 | #endif | ||||||
| 
 | 
 | ||||||
| #pragma once | #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 RUFUS_TEST
 | ||||||
| 
 | 
 | ||||||
| #define APPLICATION_NAME            "Rufus" | #define APPLICATION_NAME            "Rufus" | ||||||
|  | @ -67,7 +70,7 @@ | ||||||
| #define MAX_LOG_SIZE                0x7FFFFFFE | #define MAX_LOG_SIZE                0x7FFFFFFE | ||||||
| #define MAX_REFRESH                 25			// How long we should wait to refresh UI elements (in ms)
 | #define MAX_REFRESH                 25			// How long we should wait to refresh UI elements (in ms)
 | ||||||
| #define MAX_GUID_STRING_LENGTH      40 | #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_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 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
 | #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 CHECK_DRIVE_TIMEOUT         2000 | ||||||
| #define MARQUEE_TIMER_REFRESH       10			// Time between progress bar marquee refreshes, in ms
 | #define MARQUEE_TIMER_REFRESH       10			// Time between progress bar marquee refreshes, in ms
 | ||||||
| #define FS_DEFAULT                  FS_FAT32 | #define FS_DEFAULT                  FS_FAT32 | ||||||
| #define CASPER_PARTITION_DEFAULT    2 |  | ||||||
| #define SINGLE_CLUSTERSIZE_DEFAULT  0x00000100 | #define SINGLE_CLUSTERSIZE_DEFAULT  0x00000100 | ||||||
| #define BADLOCKS_PATTERN_TYPES      3 | #define BADLOCKS_PATTERN_TYPES      3 | ||||||
| #define BADBLOCK_PATTERN_COUNT      4 | #define BADBLOCK_PATTERN_COUNT      4 | ||||||
|  | @ -118,7 +120,7 @@ | ||||||
| #endif | #endif | ||||||
| #define IsChecked(CheckBox_ID)      (IsDlgButtonChecked(hMainDialog, CheckBox_ID) == BST_CHECKED) | #define IsChecked(CheckBox_ID)      (IsDlgButtonChecked(hMainDialog, CheckBox_ID) == BST_CHECKED) | ||||||
| #define MB_IS_RTL                   (right_to_left_mode?MB_RTLREADING|MB_RIGHT:0) | #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
 | // Bit masks used for the display of additional image options in the UI
 | ||||||
| #define IMOP_WINTOGO                0x01 | #define IMOP_WINTOGO                0x01 | ||||||
| #define IMOP_PERSISTENCE            0x02 | #define IMOP_PERSISTENCE            0x02 | ||||||
|  | @ -243,6 +245,9 @@ enum fs_type { | ||||||
| 	FS_UDF, | 	FS_UDF, | ||||||
| 	FS_EXFAT, | 	FS_EXFAT, | ||||||
| 	FS_REFS, | 	FS_REFS, | ||||||
|  | 	FS_EXT2, | ||||||
|  | 	FS_EXT3, | ||||||
|  | 	FS_EXT4, | ||||||
| 	FS_MAX | 	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 | IDD_DIALOG DIALOGEX 12, 12, 232, 326 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 3.6.1527" | CAPTION "Rufus 3.6.1528" | ||||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP |     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||||
|  | @ -394,8 +394,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 3,6,1527,0 |  FILEVERSION 3,6,1528,0 | ||||||
|  PRODUCTVERSION 3,6,1527,0 |  PRODUCTVERSION 3,6,1528,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -413,13 +413,13 @@ BEGIN | ||||||
|             VALUE "Comments", "https://akeo.ie" |             VALUE "Comments", "https://akeo.ie" | ||||||
|             VALUE "CompanyName", "Akeo Consulting" |             VALUE "CompanyName", "Akeo Consulting" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "3.6.1527" |             VALUE "FileVersion", "3.6.1528" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html" |             VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html" | ||||||
|             VALUE "OriginalFilename", "rufus-3.6.exe" |             VALUE "OriginalFilename", "rufus-3.6.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "3.6.1527" |             VALUE "ProductVersion", "3.6.1528" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
|  | @ -43,8 +43,10 @@ extern char* ini_file; | ||||||
| #define SETTING_LAST_UPDATE                 "LastUpdateCheck" | #define SETTING_LAST_UPDATE                 "LastUpdateCheck" | ||||||
| #define SETTING_LOCALE                      "Locale" | #define SETTING_LOCALE                      "Locale" | ||||||
| #define SETTING_UPDATE_INTERVAL             "UpdateCheckInterval" | #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_PROPER_SIZE_UNITS       "UseProperSizeUnits" | ||||||
|  | #define SETTING_USE_UDF_VERSION             "UseUdfVersion" | ||||||
|  | #define SETTING_USE_VDS                     "UseVds" | ||||||
| #define SETTING_PRESERVE_TIMESTAMPS         "PreserveTimestamps" | #define SETTING_PRESERVE_TIMESTAMPS         "PreserveTimestamps" | ||||||
| #define SETTING_VERBOSE_UPDATES             "VerboseUpdateCheck" | #define SETTING_VERBOSE_UPDATES             "VerboseUpdateCheck" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -272,7 +272,7 @@ const char* _StrError(DWORD error_code) | ||||||
| 		return lmprintf(MSG_050); | 		return lmprintf(MSG_050); | ||||||
| 	} | 	} | ||||||
| 	if (SCODE_FACILITY(error_code) != FACILITY_STORAGE) { | 	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); | 		SetLastError(error_code); | ||||||
| 		return WindowsErrorString(); | 		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 | 	 * weird reason.the Syslinux install process *MUST* have FILE_SHARE_WRITE | ||||||
| 	 * on the volume, or else creating 'ldlinux.sys' will fail... | 	 * 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)) { | 	if ((d_handle == INVALID_HANDLE_VALUE) || (d_handle == NULL)) { | ||||||
| 		uprintf("Could open volume for Syslinux installation"); | 		uprintf("Could open volume for Syslinux installation"); | ||||||
| 		goto out; | 		goto out; | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								src/ui.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/ui.c
									
										
									
									
									
								
							|  | @ -43,7 +43,7 @@ | ||||||
| 
 | 
 | ||||||
| UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU; | UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU; | ||||||
| HIMAGELIST hUpImageList, hDownImageList; | HIMAGELIST hUpImageList, hDownImageList; | ||||||
| extern BOOL enable_fido; | extern BOOL enable_fido, use_vds; | ||||||
| int advanced_device_section_height, advanced_format_section_height; | int advanced_device_section_height, advanced_format_section_height; | ||||||
| // (empty) check box width, (empty) drop down width, button height (for and without dropdown match)
 | // (empty) check box width, (empty) drop down width, button height (for and without dropdown match)
 | ||||||
| int cbw, ddw, ddbh = 0, bh = 0; | int cbw, ddw, ddbh = 0, bh = 0; | ||||||
|  | @ -1168,20 +1168,21 @@ void InitProgress(BOOL bOnlyFormat) | ||||||
| 			nb_slots[OP_ZERO_MBR] = 1; | 			nb_slots[OP_ZERO_MBR] = 1; | ||||||
| 			nb_slots[OP_PARTITION] = 1; | 			nb_slots[OP_PARTITION] = 1; | ||||||
| 			nb_slots[OP_FIX_MBR] = 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))]; | 				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
 | 			// 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
 | 			// 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...
 | 			// partitions. Maybe one day I'll be bothered to handle two separate OP_FORMAT ops...
 | ||||||
| 			if ((!IsChecked(IDC_QUICK_FORMAT)) || (persistence_size != 0) | 			if ((!IsChecked(IDC_QUICK_FORMAT)) || (persistence_size != 0) || | ||||||
| 				|| ((fs_type == FS_FAT32) && ((SelectedDrive.DiskSize >= LARGE_FAT32_SIZE) || (force_large_fat32)))) { | 				((fs_type == FS_FAT32) && ((SelectedDrive.DiskSize >= LARGE_FAT32_SIZE) || (force_large_fat32)))) { | ||||||
| 				nb_slots[OP_FORMAT] = -1; | 				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; | 			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) { | 		if (nb_slots[i] > 0) { | ||||||
| 			slots_discrete += nb_slots[i] * 1.0f; | 			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) { | 		if (nb_slots[i] == 0) { | ||||||
| 			slot_end[i + 1] = last_end; | 			slot_end[i + 1] = last_end; | ||||||
| 		} else if (nb_slots[i] > 0) { | 		} 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 there's no analog, adjust our discrete ends to fill the whole bar
 | ||||||
| 	if (slots_analog == 0.0f) { | 	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; | 			slot_end[i + 1] *= 100.0f / slots_discrete; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue