From c0526b3e8b21bafdd6992c79323e19d65109ba59 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Wed, 28 Nov 2018 10:50:00 +0000 Subject: [PATCH] [core] invoke VDS to delete all partitions before format/write --- ChangeLog.txt | 1 + src/drive.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/drive.h | 154 ++++++++++++++++++++++++++++++++++ src/format.c | 21 ++++- src/rufus.c | 2 +- src/rufus.rc | 10 +-- 6 files changed, 397 insertions(+), 17 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 644d6ea2..48dfb1ea 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -2,6 +2,7 @@ o Version 3.4 (2018.12.??) Set the default image selection directory to Downloads\ instead of My Documents\ Add ARM/ARM64 automatic update support 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 Fix broken detection of some EFI based images Fix broken update check due to new server diff --git a/src/drive.c b/src/drive.c index 16c4cec4..199a6d63 100644 --- a/src/drive.c +++ b/src/drive.c @@ -26,6 +26,10 @@ #include #include #include +#if !defined(__MINGW32__) +#include +#endif +#include #include "rufus.h" #include "missing.h" @@ -54,6 +58,16 @@ const GUID PARTITION_SYSTEM_GUID = { 0xc12a7328L, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} }; #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)); /* @@ -112,6 +126,7 @@ BOOL GetAutoMount(BOOL* enabled) * the specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX]. */ #define CheckDriveIndex(DriveIndex) do { \ + if ((int)DriveIndex < 0) goto out; \ assert((DriveIndex >= DRIVE_INDEX_MIN) && (DriveIndex <= DRIVE_INDEX_MAX)); \ if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) goto out; \ 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("Requesting lock..."); EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT; do { if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL)) @@ -208,7 +222,7 @@ char* GetPhysicalName(DWORD DriveIndex) char physical_name[24]; CheckDriveIndex(DriveIndex); - static_sprintf(physical_name, "\\\\.\\PHYSICALDRIVE%lu", DriveIndex); + static_sprintf(physical_name, "\\\\.\\PhysicalDrive%lu", DriveIndex); success = TRUE; out: return (success)?safe_strdup(physical_name):NULL; @@ -247,7 +261,7 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent CheckDriveIndex(DriveIndex); - for (i=0; hDrive == INVALID_HANDLE_VALUE; i++) { + for (i = 0; hDrive == INVALID_HANDLE_VALUE; i++) { if (i == 0) { hVolume = FindFirstVolumeA(volume_name, sizeof(volume_name)); if (hVolume == INVALID_HANDLE_VALUE) { @@ -265,10 +279,9 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent // Sanity checks len = safe_strlen(volume_name); - if ((len <= 1) || (safe_strnicmp(volume_name, volume_start, 4) != 0) || (volume_name[len-1] != '\\')) { - suprintf("'%s' is not a GUID volume name", volume_name); - continue; - } + assert(len > 4); + assert(safe_strnicmp(volume_name, volume_start, 4) == 0); + assert(volume_name[len - 1] == '\\'); drive_type = GetDriveTypeA(volume_name); if ((drive_type != DRIVE_REMOVABLE) && (drive_type != DRIVE_FIXED)) @@ -316,6 +329,205 @@ out: 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 */ BOOL WaitForLogical(DWORD DriveIndex) { diff --git a/src/drive.h b/src/drive.h index d1722c55..30c870d2 100644 --- a/src/drive.h +++ b/src/drive.h @@ -73,6 +73,159 @@ typedef struct _FILE_FS_DEVICE_INFORMATION { DEVICE_TYPE DeviceType; ULONG Characteristics; } FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; +#else +/* MinGW is currently missing all the VDS COM stuff */ +#include +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 static __inline BOOL UnlockDrive(HANDLE hDrive) { @@ -105,6 +258,7 @@ extern RUFUS_DRIVE_INFO SelectedDrive; BOOL SetAutoMount(BOOL enable); BOOL GetAutoMount(BOOL* enabled); char* GetPhysicalName(DWORD DriveIndex); +BOOL DeletePartitions(DWORD DriveIndex); HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare); char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent); BOOL WaitForLogical(DWORD DriveIndex); diff --git a/src/format.c b/src/format.c index 003b54e3..e1d6d2b7 100644 --- a/src/format.c +++ b/src/format.c @@ -1760,13 +1760,13 @@ DWORD WINAPI FormatThread(void* param) extra_partitions = XP_COMPAT; 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) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; 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)) { uprintf("Failed to get a drive letter\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_ASSIGN_LETTER); @@ -1783,7 +1783,7 @@ DWORD WINAPI FormatThread(void* param) } else { // Unmount all mounted volumes that belong to this drive // 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]; if (bt == BT_IMAGE) { // 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]); - // ...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); if (hLogicalVolume == INVALID_HANDLE_VALUE) { uprintf("Could not lock volume\n"); diff --git a/src/rufus.c b/src/rufus.c index d114b845..56fa2bde 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -1884,7 +1884,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case WM_COMMAND: #ifdef RUFUS_TEST if (LOWORD(wParam) == IDC_TEST) { - assert(1 == 0); + DeletePartitions((DWORD)ComboBox_GetItemData(hDeviceList, ComboBox_GetCurSel(hDeviceList))); break; } #endif diff --git a/src/rufus.rc b/src/rufus.rc index 007c993c..b0e6ca80 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 3.4.1427" +CAPTION "Rufus 3.4.1428" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -394,8 +394,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,4,1427,0 - PRODUCTVERSION 3,4,1427,0 + FILEVERSION 3,4,1428,0 + PRODUCTVERSION 3,4,1428,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -413,13 +413,13 @@ BEGIN VALUE "Comments", "https://akeo.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.4.1427" + VALUE "FileVersion", "3.4.1428" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", " 2011-2018 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus-3.4.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.4.1427" + VALUE "ProductVersion", "3.4.1428" END END BLOCK "VarFileInfo"