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:
parent
7745edbb92
commit
c0526b3e8b
6 changed files with 397 additions and 17 deletions
|
@ -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
|
||||
|
|
226
src/drive.c
226
src/drive.c
|
@ -26,6 +26,10 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#if !defined(__MINGW32__)
|
||||
#include <initguid.h>
|
||||
#endif
|
||||
#include <vds.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
|
|
154
src/drive.h
154
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 <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
|
||||
|
||||
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);
|
||||
|
|
21
src/format.c
21
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");
|
||||
|
|
|
@ -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
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 3.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"
|
||||
|
|
Loading…
Reference in a new issue