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

[core] invoke VDS to delete all partitions before format/write

This commit is contained in:
Pete Batard 2018-11-28 10:50:00 +00:00
parent 7745edbb92
commit c0526b3e8b
No known key found for this signature in database
GPG key ID: 38E0CF5E69EDD671
6 changed files with 397 additions and 17 deletions

View file

@ -2,6 +2,7 @@ o Version 3.4 (2018.12.??)
Set the default image selection directory to Downloads\ instead of My Documents\ Set the default image selection directory to Downloads\ instead of My Documents\
Add ARM/ARM64 automatic update support Add ARM/ARM64 automatic update support
Improve UEFI:NTFS compatibility Improve UEFI:NTFS compatibility
Improve access issues by using VDS to delete all partitions
Update the .appx to include all architectures as well as request elevation Update the .appx to include all architectures as well as request elevation
Fix broken detection of some EFI based images Fix broken detection of some EFI based images
Fix broken update check due to new server Fix broken update check due to new server

View file

@ -26,6 +26,10 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h> #include <assert.h>
#if !defined(__MINGW32__)
#include <initguid.h>
#endif
#include <vds.h>
#include "rufus.h" #include "rufus.h"
#include "missing.h" #include "missing.h"
@ -54,6 +58,16 @@ const GUID PARTITION_SYSTEM_GUID =
{ 0xc12a7328L, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} }; { 0xc12a7328L, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} };
#endif #endif
#if defined(__MINGW32__)
const IID CLSID_VdsLoader = { 0x9c38ed61, 0xd565, 0x4728, { 0xae, 0xee, 0xc8, 0x09, 0x52, 0xf0, 0xec, 0xde } };
const IID IID_IVdsServiceLoader = { 0xe0393303, 0x90d4, 0x4a97, { 0xab, 0x71, 0xe9, 0xb6, 0x71, 0xee, 0x27, 0x29 } };
const IID IID_IVdsProvider = { 0x10c5e575, 0x7984, 0x4e81, { 0xa5, 0x6b, 0x43, 0x1f, 0x5f, 0x92, 0xae, 0x42 } };
const IID IID_IVdsSwProvider = { 0x9aa58360, 0xce33, 0x4f92, { 0xb6, 0x58, 0xed, 0x24, 0xb1, 0x44, 0x25, 0xb8 } };
const IID IID_IVdsPack = { 0x3b69d7f5, 0x9d94, 0x4648, { 0x91, 0xca, 0x79, 0x93, 0x9b, 0xa2, 0x63, 0xbf } };
const IID IID_IVdsDisk = { 0x07e5c822, 0xf00c, 0x47a1, { 0x8f, 0xce, 0xb2, 0x44, 0xda, 0x56, 0xfd, 0x06 } };
const IID IID_IVdsAdvancedDisk = { 0x6e6f6b40, 0x977c, 0x4069, { 0xbd, 0xdd, 0xac, 0x71, 0x00, 0x59, 0xf8, 0xc0 } };
#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));
/* /*
@ -112,6 +126,7 @@ BOOL GetAutoMount(BOOL* enabled)
* the specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX]. * the specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX].
*/ */
#define CheckDriveIndex(DriveIndex) do { \ #define CheckDriveIndex(DriveIndex) do { \
if ((int)DriveIndex < 0) goto out; \
assert((DriveIndex >= DRIVE_INDEX_MIN) && (DriveIndex <= DRIVE_INDEX_MAX)); \ assert((DriveIndex >= DRIVE_INDEX_MIN) && (DriveIndex <= DRIVE_INDEX_MAX)); \
if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) goto out; \ if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) goto out; \
DriveIndex -= DRIVE_INDEX_MIN; } while (0) DriveIndex -= DRIVE_INDEX_MIN; } while (0)
@ -175,7 +190,6 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr
uprintf("I/O boundary checks disabled"); uprintf("I/O boundary checks disabled");
} }
uprintf("Requesting lock...");
EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT; EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;
do { do {
if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL)) if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))
@ -208,7 +222,7 @@ char* GetPhysicalName(DWORD DriveIndex)
char physical_name[24]; char physical_name[24];
CheckDriveIndex(DriveIndex); CheckDriveIndex(DriveIndex);
static_sprintf(physical_name, "\\\\.\\PHYSICALDRIVE%lu", DriveIndex); static_sprintf(physical_name, "\\\\.\\PhysicalDrive%lu", DriveIndex);
success = TRUE; success = TRUE;
out: out:
return (success)?safe_strdup(physical_name):NULL; return (success)?safe_strdup(physical_name):NULL;
@ -247,7 +261,7 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent
CheckDriveIndex(DriveIndex); CheckDriveIndex(DriveIndex);
for (i=0; hDrive == INVALID_HANDLE_VALUE; i++) { for (i = 0; hDrive == INVALID_HANDLE_VALUE; i++) {
if (i == 0) { if (i == 0) {
hVolume = FindFirstVolumeA(volume_name, sizeof(volume_name)); hVolume = FindFirstVolumeA(volume_name, sizeof(volume_name));
if (hVolume == INVALID_HANDLE_VALUE) { if (hVolume == INVALID_HANDLE_VALUE) {
@ -265,10 +279,9 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent
// Sanity checks // Sanity checks
len = safe_strlen(volume_name); len = safe_strlen(volume_name);
if ((len <= 1) || (safe_strnicmp(volume_name, volume_start, 4) != 0) || (volume_name[len-1] != '\\')) { assert(len > 4);
suprintf("'%s' is not a GUID volume name", volume_name); assert(safe_strnicmp(volume_name, volume_start, 4) == 0);
continue; assert(volume_name[len - 1] == '\\');
}
drive_type = GetDriveTypeA(volume_name); drive_type = GetDriveTypeA(volume_name);
if ((drive_type != DRIVE_REMOVABLE) && (drive_type != DRIVE_FIXED)) if ((drive_type != DRIVE_REMOVABLE) && (drive_type != DRIVE_FIXED))
@ -316,6 +329,205 @@ out:
return (success)?safe_strdup(volume_name):NULL; return (success)?safe_strdup(volume_name):NULL;
} }
/*
* Delete all the partitions from a disk, using VDS
* Mostly copied from https://social.msdn.microsoft.com/Forums/vstudio/en-US/b90482ae-4e44-4b08-8731-81915030b32a/createpartition-using-vds-interface-throw-error-enointerface-dcom?forum=vcgeneral
*/
BOOL DeletePartitions(DWORD DriveIndex)
{
BOOL r = FALSE;
HRESULT hr;
ULONG ulFetched;
wchar_t wPhysicalName[24];
IVdsServiceLoader *pLoader;
IVdsService *pService;
IEnumVdsObject *pEnum;
IUnknown *pUnk;
CheckDriveIndex(DriveIndex);
wnsprintf(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%lu", DriveIndex);
// Initialize COM
IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
IGNORE_RETVAL(CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL));
// Create a VDS Loader Instance
hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
&IID_IVdsServiceLoader, (void **)&pLoader);
if (hr != S_OK) {
uprintf("Could not create VDS Loader Instance: hr=%X\n", hr);
goto out;
}
// Load the VDS Service
hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);
IVdsServiceLoader_Release(pLoader);
if (hr != S_OK) {
uprintf("Could not load VDS Service: 0x%08X", hr);
goto out;
}
// Query the VDS Service Providers
hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
if (hr != S_OK) {
uprintf("Could not query VDS Service Providers: 0x%08X", hr);
goto out;
}
while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK) {
IVdsProvider *pProvider;
IVdsSwProvider *pSwProvider;
IEnumVdsObject *pEnumPack;
IUnknown *pPackUnk;
// Get VDS Provider
hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider);
IUnknown_Release(pUnk);
if (hr != S_OK) {
uprintf("Could not get VDS Provider: 0x%08X", hr);
goto out;
}
// Get VDS Software Provider
hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider);
IVdsProvider_Release(pProvider);
if (hr != S_OK) {
uprintf("Could not get VDS Software Provider: 0x%08X", hr);
goto out;
}
// Get VDS Software Provider Packs
hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack);
IVdsSwProvider_Release(pSwProvider);
if (hr != S_OK) {
uprintf("Could not get VDS Software Provider Packs: 0x%08X", hr);
goto out;
}
// Enumerate Provider Packs
while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) {
IVdsPack *pPack;
IEnumVdsObject *pEnumDisk;
IUnknown *pDiskUnk;
hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack);
IUnknown_Release(pPackUnk);
if (hr != S_OK) {
uprintf("Could not query VDS Software Provider Pack: 0x%08X", hr);
goto out;
}
// Use the pack interface to access the disks
hr = IVdsPack_QueryDisks(pPack, &pEnumDisk);
if (hr != S_OK) {
uprintf("Could not query VDS disks: 0x%08X", hr);
goto out;
}
// List disks
while (IEnumVdsObject_Next(pEnumDisk, 1, &pDiskUnk, &ulFetched) == S_OK) {
VDS_DISK_PROP diskprop;
VDS_PARTITION_PROP* prop_array;
LONG i, prop_array_size;
IVdsDisk *pDisk;
IVdsAdvancedDisk *pAdvancedDisk;
// Get the disk interface.
hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk);
if (hr != S_OK) {
uprintf("Could not query VDS Disk Interface: 0x%08X", hr);
goto out;
}
// Get the disk properties
hr = IVdsDisk_GetProperties(pDisk, &diskprop);
if (hr != S_OK) {
uprintf("Could not query VDS Disk Properties: 0x%08X", hr);
goto out;
}
// Isolate the disk we want
if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) {
IVdsDisk_Release(pDisk);
continue;
}
// Instantiate the AdvanceDisk interface for our disk.
hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk);
IVdsDisk_Release(pDisk);
if (hr != S_OK) {
uprintf("Could not access VDS Advanced Disk interface: 0x%08X", hr);
goto out;
}
// Query the partition data, so we can get the start offset, which we need for deletion
hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size);
if (hr != S_OK) {
uprintf("No partition to delete on disk '%ws'", diskprop.pwszName);
goto out;
}
uprintf("Deleting ALL partitions from disk '%ws':", diskprop.pwszName);
// Now go through each partition
r = (prop_array_size >= 1);
for (i = 0; i < prop_array_size; i++) {
uprintf("● Partition %d (offset: %lld, size: %s)", prop_array[i].ulPartitionNumber,
prop_array[i].ullOffset, SizeToHumanReadable(prop_array[i].ullSize, FALSE, FALSE));
hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);
if (hr != S_OK) {
r = FALSE;
uprintf("Could not delete partitions: 0x%08X", hr);
}
}
CoTaskMemFree(prop_array);
// NB: In the future, we could try something like this to format partitions:
#if 0
// Initiate formatting and wait for completion.
LPWSTR pwszLabel[8] = L"TEST";
ULONGLONG Offset = 1024 * 1024;
BOOL QuickFormat = TRUE;
BOOL EnableCompression = FALSE;
IVdsAsync* pAsync;
hr = IVdsAdvancedDisk_FormatPartition(pAdvancedDisk, Offset, FileSystemType,
pwszLabel, 0, TRUE, QuickFormat, EnableCompression, &pAsync);
if (hr != S_OK) {
uprintf("Could not start formatting: 0x%08X", hr);
goto out;
}
VDS_ASYNC_OUTPUT AsyncOut;
ULONG ulPercentCompleted;
HRESULT hr2 = E_FAIL;
do {
hr = IVdsAsync_QueryStatus(pAsync, &hr2, &ulPercentCompleted);
if (SUCCEEDED(hr)) {
printf("%ld%%", ulPercentCompleted);
if ((hr2 != S_OK) && (hr2 != VDS_E_OPERATION_PENDING)) {
uprintf("hr2: %X", hr2);
break;
}
if (hr2 == S_OK) {
break;
}
}
Sleep(500);
} while (SUCCEEDED(hr));
hr = IVdsAsync_Wait(pAsync, &hr2, &AsyncOut);
IVdsAsync_Release(pAsync);
#endif
IVdsAdvancedDisk_Release(pAdvancedDisk);
goto out;
}
}
}
out:
return r;
}
/* 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)
{ {

View file

@ -73,6 +73,159 @@ typedef struct _FILE_FS_DEVICE_INFORMATION {
DEVICE_TYPE DeviceType; DEVICE_TYPE DeviceType;
ULONG Characteristics; ULONG Characteristics;
} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; } FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;
#else
/* MinGW is currently missing all the VDS COM stuff */
#include <vds.h>
typedef interface IVdsServiceLoader IVdsServiceLoader;
typedef interface IVdsService IVdsService;
typedef interface IVdsProvider IVdsProvider;
typedef interface IVdsSwProvider IVdsSwProvider;
typedef interface IEnumVdsObject IEnumVdsObject;
typedef interface IVdsPack IVdsPack;
typedef interface IVdsDisk IVdsDisk;
typedef interface IVdsAdvancedDisk IVdsAdvancedDisk;
typedef interface IVdsAdviseSink IVdsAdviseSink;
typedef interface IVdsAsync IVdsAsync;
typedef struct IVdsServiceLoaderVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsServiceLoader *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsServiceLoader *This);
ULONG(STDMETHODCALLTYPE *Release)(__RPC__in IVdsServiceLoader *This);
HRESULT(STDMETHODCALLTYPE *LoadService)(__RPC__in IVdsServiceLoader *This, __RPC__in_opt_string LPWSTR pwszMachineName, __RPC__deref_out_opt IVdsService **ppService);
} IVdsServiceLoaderVtbl;
interface IVdsServiceLoader {
CONST_VTBL struct IVdsServiceLoaderVtbl *lpVtbl;
};
typedef struct IVdsServiceVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsService *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsService *This);
ULONG(STDMETHODCALLTYPE *Release)(__RPC__in IVdsService *This);
HRESULT(STDMETHODCALLTYPE *IsServiceReady)(__RPC__in IVdsService *This);
HRESULT(STDMETHODCALLTYPE *WaitForServiceReady)(__RPC__in IVdsService *This);
HRESULT(STDMETHODCALLTYPE *GetProperties)(__RPC__in IVdsService *This, __RPC__out VDS_SERVICE_PROP *pServiceProp);
HRESULT(STDMETHODCALLTYPE *QueryProviders)(__RPC__in IVdsService *This, DWORD masks, __RPC__deref_out_opt IEnumVdsObject **ppEnum);
HRESULT(STDMETHODCALLTYPE *QueryMaskedDisks)(__RPC__in IVdsService *This, __RPC__deref_out_opt IEnumVdsObject **ppEnum);
HRESULT(STDMETHODCALLTYPE *QueryUnallocatedDisks)(__RPC__in IVdsService *This, __RPC__deref_out_opt IEnumVdsObject **ppEnum);
HRESULT(STDMETHODCALLTYPE *GetObject)(__RPC__in IVdsService *This, VDS_OBJECT_ID ObjectId, VDS_OBJECT_TYPE type, __RPC__deref_out_opt IUnknown **ppObjectUnk);
HRESULT(STDMETHODCALLTYPE *QueryDriveLetters)(__RPC__in IVdsService *This, WCHAR wcFirstLetter, DWORD count, __RPC__out_ecount_full(count) VDS_DRIVE_LETTER_PROP *pDriveLetterPropArray);
HRESULT(STDMETHODCALLTYPE *QueryFileSystemTypes)(__RPC__in IVdsService *This, __RPC__deref_out_ecount_full_opt(*plNumberOfFileSystems) VDS_FILE_SYSTEM_TYPE_PROP **ppFileSystemTypeProps, __RPC__out LONG *plNumberOfFileSystems);
HRESULT(STDMETHODCALLTYPE *Reenumerate)(__RPC__in IVdsService *This);
HRESULT(STDMETHODCALLTYPE *Refresh)(__RPC__in IVdsService *This);
HRESULT(STDMETHODCALLTYPE *CleanupObsoleteMountPoints)(__RPC__in IVdsService *This);
HRESULT(STDMETHODCALLTYPE *Advise)(__RPC__in IVdsService *This, __RPC__in_opt IVdsAdviseSink *pSink, __RPC__out DWORD *pdwCookie);
HRESULT(STDMETHODCALLTYPE *Unadvise)(__RPC__in IVdsService *This, DWORD dwCookie);
HRESULT(STDMETHODCALLTYPE *Reboot)(__RPC__in IVdsService *This);
HRESULT(STDMETHODCALLTYPE *SetFlags)(__RPC__in IVdsService *This, ULONG ulFlags);
HRESULT(STDMETHODCALLTYPE *ClearFlags)(__RPC__in IVdsService *This, ULONG ulFlags);
} IVdsServiceVtbl;
interface IVdsService {
CONST_VTBL struct IVdsServiceVtbl *lpVtbl;
};
typedef struct IEnumVdsObjectVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IEnumVdsObject *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(__RPC__in IEnumVdsObject *This);
ULONG(STDMETHODCALLTYPE *Release)(__RPC__in IEnumVdsObject *This);
HRESULT(STDMETHODCALLTYPE *Next)(__RPC__in IEnumVdsObject *This, ULONG celt, __RPC__out_ecount_part(celt, *pcFetched) IUnknown **ppObjectArray, __RPC__out ULONG *pcFetched);
HRESULT(STDMETHODCALLTYPE *Skip)(__RPC__in IEnumVdsObject *This, ULONG celt);
HRESULT(STDMETHODCALLTYPE *Reset)(__RPC__in IEnumVdsObject *This);
HRESULT(STDMETHODCALLTYPE *Clone)(__RPC__in IEnumVdsObject *This, __RPC__deref_out_opt IEnumVdsObject **ppEnum);
} IEnumVdsObjectVtbl;
interface IEnumVdsObject {
CONST_VTBL struct IEnumVdsObjectVtbl *lpVtbl;
};
typedef struct IVdsProviderVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsProvider *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsProvider *This);
ULONG(STDMETHODCALLTYPE *Release)(__RPC__in IVdsProvider *This);
HRESULT(STDMETHODCALLTYPE *GetProperties)(__RPC__in IVdsProvider *This, __RPC__out VDS_PROVIDER_PROP *pProviderProp);
} IVdsProviderVtbl;
interface IVdsProvider {
CONST_VTBL struct IVdsProviderVtbl *lpVtbl;
};
typedef struct IVdsSwProviderVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsSwProvider *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsSwProvider *This);
ULONG(STDMETHODCALLTYPE *Release)(__RPC__in IVdsSwProvider *This);
HRESULT(STDMETHODCALLTYPE *QueryPacks)(__RPC__in IVdsSwProvider *This, __RPC__deref_out_opt IEnumVdsObject **ppEnum);
HRESULT(STDMETHODCALLTYPE *CreatePack)(__RPC__in IVdsSwProvider *This, __RPC__deref_out_opt IVdsPack **ppPack);
} IVdsSwProviderVtbl;
interface IVdsSwProvider {
CONST_VTBL struct IVdsSwProviderVtbl *lpVtbl;
};
typedef struct IVdsPackVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsPack *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsPack *This);
ULONG(STDMETHODCALLTYPE *Release)(__RPC__in IVdsPack *This);
HRESULT(STDMETHODCALLTYPE *GetProperties)(__RPC__in IVdsPack *This, __RPC__out VDS_PACK_PROP *pPackProp);
HRESULT(STDMETHODCALLTYPE *GetProvider)(__RPC__in IVdsPack *This, __RPC__deref_out_opt IVdsProvider **ppProvider);
HRESULT(STDMETHODCALLTYPE *QueryVolumes)(__RPC__in IVdsPack *This, __RPC__deref_out_opt IEnumVdsObject **ppEnum);
HRESULT(STDMETHODCALLTYPE *QueryDisks)(__RPC__in IVdsPack *This, __RPC__deref_out_opt IEnumVdsObject **ppEnum);
HRESULT(STDMETHODCALLTYPE *CreateVolume)(__RPC__in IVdsPack *This, VDS_VOLUME_TYPE type, __RPC__in_ecount_full(lNumberOfDisks) VDS_INPUT_DISK *pInputDiskArray, LONG lNumberOfDisks, ULONG ulStripeSize, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT(STDMETHODCALLTYPE *AddDisk)(__RPC__in IVdsPack *This, VDS_OBJECT_ID DiskId, VDS_PARTITION_STYLE PartitionStyle, BOOL bAsHotSpare);
HRESULT(STDMETHODCALLTYPE *MigrateDisks)(__RPC__in IVdsPack *This, __RPC__in_ecount_full(lNumberOfDisks) VDS_OBJECT_ID *pDiskArray, LONG lNumberOfDisks, VDS_OBJECT_ID TargetPack, BOOL bForce, BOOL bQueryOnly, __RPC__out_ecount_full(lNumberOfDisks) HRESULT *pResults, __RPC__out BOOL *pbRebootNeeded);
HRESULT(STDMETHODCALLTYPE *ReplaceDisk)(__RPC__in IVdsPack *This, VDS_OBJECT_ID OldDiskId, VDS_OBJECT_ID NewDiskId, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT(STDMETHODCALLTYPE *RemoveMissingDisk)(__RPC__in IVdsPack *This, VDS_OBJECT_ID DiskId);
HRESULT(STDMETHODCALLTYPE *Recover)(__RPC__in IVdsPack *This, __RPC__deref_out_opt IVdsAsync **ppAsync);
} IVdsPackVtbl;
interface IVdsPack {
CONST_VTBL struct IVdsPackVtbl *lpVtbl;
};
typedef struct IVdsDiskVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsDisk *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsDisk *This);
ULONG(STDMETHODCALLTYPE *Release)(__RPC__in IVdsDisk *This);
HRESULT(STDMETHODCALLTYPE *GetProperties)(__RPC__in IVdsDisk *This, __RPC__out VDS_DISK_PROP *pDiskProperties);
HRESULT(STDMETHODCALLTYPE *GetPack)(__RPC__in IVdsDisk *This, __RPC__deref_out_opt IVdsPack **ppPack);
HRESULT(STDMETHODCALLTYPE *GetIdentificationData)(__RPC__in IVdsDisk *This, __RPC__out VDS_LUN_INFORMATION *pLunInfo);
HRESULT(STDMETHODCALLTYPE *QueryExtents)(__RPC__in IVdsDisk *This, __RPC__deref_out_ecount_full_opt(*plNumberOfExtents) VDS_DISK_EXTENT **ppExtentArray, __RPC__out LONG *plNumberOfExtents);
HRESULT(STDMETHODCALLTYPE *ConvertStyle)(__RPC__in IVdsDisk *This, VDS_PARTITION_STYLE NewStyle);
HRESULT(STDMETHODCALLTYPE *SetFlags)(__RPC__in IVdsDisk *This, ULONG ulFlags);
HRESULT(STDMETHODCALLTYPE *ClearFlags)(__RPC__in IVdsDisk *This, ULONG ulFlags);
} IVdsDiskVtbl;
interface IVdsDisk {
CONST_VTBL struct IVdsDiskVtbl *lpVtbl;
};
typedef struct IVdsAdvancedDiskVtbl {
HRESULT(STDMETHODCALLTYPE *QueryInterface)(__RPC__in IVdsAdvancedDisk *This, __RPC__in REFIID riid, _COM_Outptr_ void **ppvObject);
ULONG(STDMETHODCALLTYPE *AddRef)(__RPC__in IVdsAdvancedDisk *This);
ULONG(STDMETHODCALLTYPE *Release)(__RPC__in IVdsAdvancedDisk *This);
HRESULT(STDMETHODCALLTYPE *GetPartitionProperties)(__RPC__in IVdsAdvancedDisk *This, ULONGLONG ullOffset, __RPC__out VDS_PARTITION_PROP *pPartitionProp);
HRESULT(STDMETHODCALLTYPE *QueryPartitions)(__RPC__in IVdsAdvancedDisk *This, __RPC__deref_out_ecount_full_opt(*plNumberOfPartitions) VDS_PARTITION_PROP **ppPartitionPropArray, __RPC__out LONG *plNumberOfPartitions);
HRESULT(STDMETHODCALLTYPE *CreatePartition)(__RPC__in IVdsAdvancedDisk *This, ULONGLONG ullOffset, ULONGLONG ullSize, __RPC__in CREATE_PARTITION_PARAMETERS *para, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT(STDMETHODCALLTYPE *DeletePartition)(__RPC__in IVdsAdvancedDisk *This, ULONGLONG ullOffset, BOOL bForce, BOOL bForceProtected);
HRESULT(STDMETHODCALLTYPE *ChangeAttributes)(__RPC__in IVdsAdvancedDisk *This, ULONGLONG ullOffset, __RPC__in CHANGE_ATTRIBUTES_PARAMETERS *para);
HRESULT(STDMETHODCALLTYPE *AssignDriveLetter)(__RPC__in IVdsAdvancedDisk *This, ULONGLONG ullOffset, WCHAR wcLetter);
HRESULT(STDMETHODCALLTYPE *DeleteDriveLetter)(__RPC__in IVdsAdvancedDisk *This, ULONGLONG ullOffset, WCHAR wcLetter);
HRESULT(STDMETHODCALLTYPE *GetDriveLetter)(__RPC__in IVdsAdvancedDisk *This, ULONGLONG ullOffset, __RPC__out WCHAR *pwcLetter);
HRESULT(STDMETHODCALLTYPE *FormatPartition)(__RPC__in IVdsAdvancedDisk *This, ULONGLONG ullOffset, VDS_FILE_SYSTEM_TYPE type, __RPC__in_string LPWSTR pwszLabel, DWORD dwUnitAllocationSize, BOOL bForce, BOOL bQuickFormat, BOOL bEnableCompression, __RPC__deref_out_opt IVdsAsync **ppAsync);
HRESULT(STDMETHODCALLTYPE *Clean)(__RPC__in IVdsAdvancedDisk *This, BOOL bForce, BOOL bForceOEM, BOOL bFullClean, __RPC__deref_out_opt IVdsAsync **ppAsync);
} IVdsAdvancedDiskVtbl;
interface IVdsAdvancedDisk {
CONST_VTBL struct IVdsAdvancedDiskVtbl *lpVtbl;
};
#define IVdsServiceLoader_LoadService(This,pwszMachineName,ppService) (This)->lpVtbl->LoadService(This,pwszMachineName,ppService)
#define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This)
#define IVdsService_QueryProviders(This,masks,ppEnum) (This)->lpVtbl->QueryProviders(This,masks,ppEnum)
#define IVdsSwProvider_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
#define IVdsProvider_Release(This) (This)->lpVtbl->Release(This)
#define IVdsSwProvider_QueryPacks(This,ppEnum) (This)->lpVtbl->QueryPacks(This,ppEnum)
#define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This)
#define IVdsPack_QueryDisks(This,ppEnum) (This)->lpVtbl->QueryDisks(This,ppEnum)
#define IVdsDisk_GetProperties(This,pDiskProperties) (This)->lpVtbl->GetProperties(This,pDiskProperties)
#define IVdsDisk_Release(This) (This)->lpVtbl->Release(This)
#define IVdsDisk_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
#define IVdsAdvancedDisk_QueryPartitions(This,ppPartitionPropArray,plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This,ppPartitionPropArray,plNumberOfPartitions)
#define IVdsAdvancedDisk_DeletePartition(This,ullOffset,bForce,bForceProtected) (This)->lpVtbl->DeletePartition(This,ullOffset,bForce,bForceProtected)
#define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)
#define IEnumVdsObject_Next(This,celt,ppObjectArray,pcFetched) (This)->lpVtbl->Next(This,celt,ppObjectArray,pcFetched)
#endif #endif
static __inline BOOL UnlockDrive(HANDLE hDrive) { static __inline BOOL UnlockDrive(HANDLE hDrive) {
@ -105,6 +258,7 @@ extern RUFUS_DRIVE_INFO SelectedDrive;
BOOL SetAutoMount(BOOL enable); BOOL SetAutoMount(BOOL enable);
BOOL GetAutoMount(BOOL* enabled); BOOL GetAutoMount(BOOL* enabled);
char* GetPhysicalName(DWORD DriveIndex); char* GetPhysicalName(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, BOOL bKeepTrailingBackslash, BOOL bSilent);
BOOL WaitForLogical(DWORD DriveIndex); BOOL WaitForLogical(DWORD DriveIndex);

View file

@ -1760,13 +1760,13 @@ DWORD WINAPI FormatThread(void* param)
extra_partitions = XP_COMPAT; extra_partitions = XP_COMPAT;
PrintInfoDebug(0, MSG_225); PrintInfoDebug(0, MSG_225);
hPhysicalDrive = GetPhysicalHandle(DriveIndex, lock_drive, TRUE, !lock_drive); hPhysicalDrive = GetPhysicalHandle(DriveIndex, lock_drive, FALSE, !lock_drive);
if (hPhysicalDrive == INVALID_HANDLE_VALUE) { if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
goto out; goto out;
} }
// At this stage we should have both a handle and a lock to the physical drive... // At this stage we have both a handle and a lock to the physical drive
if (!GetDriveLetters(DriveIndex, drive_letters)) { if (!GetDriveLetters(DriveIndex, drive_letters)) {
uprintf("Failed to get a drive letter\n"); uprintf("Failed to get a drive letter\n");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_ASSIGN_LETTER); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_ASSIGN_LETTER);
@ -1783,7 +1783,7 @@ DWORD WINAPI FormatThread(void* param)
} else { } else {
// Unmount all mounted volumes that belong to this drive // Unmount all mounted volumes that belong to this drive
// Do it in reverse so that we always end on the first volume letter // Do it in reverse so that we always end on the first volume letter
for (i=(int)safe_strlen(drive_letters); i>0; i--) { for (i = (int)safe_strlen(drive_letters); i > 0; i--) {
drive_name[0] = drive_letters[i-1]; drive_name[0] = drive_letters[i-1];
if (bt == BT_IMAGE) { if (bt == BT_IMAGE) {
// If we are using an image, check that it isn't located on the drive we are trying to format // If we are using an image, check that it isn't located on the drive we are trying to format
@ -1801,7 +1801,20 @@ DWORD WINAPI FormatThread(void* param)
} }
uprintf("Will use '%c:' as volume mountpoint\n", drive_name[0]); uprintf("Will use '%c:' as volume mountpoint\n", drive_name[0]);
// ...but we need a lock to the logical drive to be able to write anything to it // It kind of blows, but we have to relinquish access to the physical drive
// for VDS to be able to delete the partitions that reside on it...
safe_unlockclose(hPhysicalDrive);
PrintInfoDebug(0, MSG_239);
DeletePartitions(DriveIndex);
// Now get RW access to the physical drive...
hPhysicalDrive = GetPhysicalHandle(DriveIndex, lock_drive, TRUE, !lock_drive);
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED;
goto out;
}
// ...and get a lock to the logical drive so that we can actually write something
hLogicalVolume = GetLogicalHandle(DriveIndex, TRUE, FALSE, !lock_drive); hLogicalVolume = GetLogicalHandle(DriveIndex, TRUE, FALSE, !lock_drive);
if (hLogicalVolume == INVALID_HANDLE_VALUE) { if (hLogicalVolume == INVALID_HANDLE_VALUE) {
uprintf("Could not lock volume\n"); uprintf("Could not lock volume\n");

View file

@ -1884,7 +1884,7 @@ 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) {
assert(1 == 0); DeletePartitions((DWORD)ComboBox_GetItemData(hDeviceList, ComboBox_GetCurSel(hDeviceList)));
break; break;
} }
#endif #endif

View file

@ -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.4.1427" CAPTION "Rufus 3.4.1428"
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,4,1427,0 FILEVERSION 3,4,1428,0
PRODUCTVERSION 3,4,1427,0 PRODUCTVERSION 3,4,1428,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.4.1427" VALUE "FileVersion", "3.4.1428"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2018 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.4.exe" VALUE "OriginalFilename", "rufus-3.4.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.4.1427" VALUE "ProductVersion", "3.4.1428"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"