[vds] improve VDS calls

* Make sure that instantiated objects are released.
* Factorize the instantiating of disk interfaces.
* Allow the provision of an offset to delete a single partition.
* Add a ListVdsVolumes() call (which is pointless since Microsoft *CRIPPLED* its VDS implementation).
This commit is contained in:
Pete Batard 2020-10-25 13:09:32 +00:00
parent 8085a2846d
commit 3758f84b17
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
5 changed files with 277 additions and 108 deletions

View File

@ -445,8 +445,8 @@ BOOL RefreshLayout(DWORD DriveIndex)
BOOL r = FALSE;
HRESULT hr;
wchar_t wPhysicalName[24];
IVdsServiceLoader *pLoader;
IVdsService *pService;
IVdsServiceLoader* pLoader = NULL;
IVdsService* pService = NULL;
IEnumVdsObject *pEnum;
CheckDriveIndex(DriveIndex);
@ -468,7 +468,6 @@ BOOL RefreshLayout(DWORD DriveIndex)
// Load the VDS Service
hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);
IVdsServiceLoader_Release(pLoader);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not load VDS Service: %s", WindowsErrorString());
@ -516,25 +515,30 @@ BOOL RefreshLayout(DWORD DriveIndex)
}
r = TRUE;
out:
return r;
out:
if (pService != NULL)
IVdsService_Release(pService);
if (pLoader != NULL)
IVdsServiceLoader_Release(pLoader);
return r;
}
/*
* 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
* Generic call to instantiate a VDS Disk Interface. 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
* See also: https://docs.microsoft.com/en-us/windows/win32/vds/working-with-enumeration-objects
*/
BOOL DeletePartitions(DWORD DriveIndex)
static BOOL GetVdsDiskInterface(DWORD DriveIndex, const IID* InterfaceIID, void** pInterfaceInstance, BOOL bSilent)
{
BOOL r = FALSE, bNeverFound = TRUE;
HRESULT hr;
HRESULT hr = S_FALSE;
ULONG ulFetched;
wchar_t wPhysicalName[24];
IVdsServiceLoader *pLoader;
IVdsService *pService;
IEnumVdsObject *pEnum;
IUnknown *pUnk;
IVdsServiceLoader* pLoader;
IVdsService* pService;
IEnumVdsObject* pEnum;
IUnknown* pUnk;
*pInterfaceInstance = NULL;
CheckDriveIndex(DriveIndex);
wnsprintf(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%lu", DriveIndex);
@ -545,10 +549,10 @@ BOOL DeletePartitions(DWORD DriveIndex)
// Create a VDS Loader Instance
hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
&IID_IVdsServiceLoader, (void **)&pLoader);
&IID_IVdsServiceLoader, (void**)&pLoader);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not create VDS Loader Instance: %s", WindowsErrorString());
suprintf("Could not create VDS Loader Instance: %s", WindowsErrorString());
goto out;
}
@ -557,7 +561,7 @@ BOOL DeletePartitions(DWORD DriveIndex)
IVdsServiceLoader_Release(pLoader);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not load VDS Service: %s", WindowsErrorString());
suprintf("Could not load VDS Service: %s", WindowsErrorString());
goto out;
}
@ -565,39 +569,40 @@ BOOL DeletePartitions(DWORD DriveIndex)
hr = IVdsService_WaitForServiceReady(pService);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("VDS Service is not ready: %s", WindowsErrorString());
suprintf("VDS Service is not ready: %s", WindowsErrorString());
goto out;
}
// Query the VDS Service Providers
hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
IVdsService_Release(pService);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not query VDS Service Providers: %s", WindowsErrorString());
suprintf("Could not query VDS Service Providers: %s", WindowsErrorString());
goto out;
}
while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK) {
IVdsProvider *pProvider;
IVdsSwProvider *pSwProvider;
IEnumVdsObject *pEnumPack;
IUnknown *pPackUnk;
IVdsProvider* pProvider;
IVdsSwProvider* pSwProvider;
IEnumVdsObject* pEnumPack;
IUnknown* pPackUnk;
// Get VDS Provider
hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider);
hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void**)&pProvider);
IUnknown_Release(pUnk);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not get VDS Provider: %s", WindowsErrorString());
suprintf("Could not get VDS Provider: %s", WindowsErrorString());
goto out;
}
// Get VDS Software Provider
hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider);
hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void**)&pSwProvider);
IVdsProvider_Release(pProvider);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not get VDS Software Provider: %s", WindowsErrorString());
suprintf("Could not get VDS Software Provider: %s", WindowsErrorString());
goto out;
}
@ -606,133 +611,293 @@ BOOL DeletePartitions(DWORD DriveIndex)
IVdsSwProvider_Release(pSwProvider);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not get VDS Software Provider Packs: %s", WindowsErrorString());
suprintf("Could not get VDS Software Provider Packs: %s", WindowsErrorString());
goto out;
}
// Enumerate Provider Packs
while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) {
IVdsPack *pPack;
IEnumVdsObject *pEnumDisk;
IUnknown *pDiskUnk;
IVdsPack* pPack;
IEnumVdsObject* pEnumDisk;
IUnknown* pDiskUnk;
hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack);
hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void**)&pPack);
IUnknown_Release(pPackUnk);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not query VDS Software Provider Pack: %s", WindowsErrorString());
suprintf("Could not query VDS Software Provider Pack: %s", WindowsErrorString());
goto out;
}
// Use the pack interface to access the disks
hr = IVdsPack_QueryDisks(pPack, &pEnumDisk);
IVdsPack_Release(pPack);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not query VDS disks: %s", WindowsErrorString());
suprintf("Could not query VDS disks: %s", WindowsErrorString());
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;
VDS_DISK_PROP prop;
IVdsDisk* pDisk;
// Get the disk interface.
hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk);
hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void**)&pDisk);
IUnknown_Release(pDiskUnk);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not query VDS Disk Interface: %s", WindowsErrorString());
suprintf("Could not query VDS Disk Interface: %s", WindowsErrorString());
goto out;
}
// Get the disk properties
hr = IVdsDisk_GetProperties(pDisk, &diskprop);
if (hr != S_OK) {
hr = IVdsDisk_GetProperties(pDisk, &prop);
if ((hr != S_OK) && (hr != VDS_S_PROPERTIES_INCOMPLETE)) {
IVdsDisk_Release(pDisk);
VDS_SET_ERROR(hr);
uprintf("Could not query VDS Disk Properties: %s", WindowsErrorString());
suprintf("Could not query VDS Disk Properties: %s", WindowsErrorString());
goto out;
}
// Isolate the disk we want
if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) {
// Check if we are on the target disk
hr = (HRESULT)_wcsicmp(wPhysicalName, prop.pwszName);
CoTaskMemFree(prop.pwszName);
if (hr != S_OK) {
IVdsDisk_Release(pDisk);
continue;
}
bNeverFound = FALSE;
// Instantiate the AdvanceDisk interface for our disk.
hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk);
// Instantiate the requested VDS disk interface
hr = IVdsDisk_QueryInterface(pDisk, InterfaceIID, pInterfaceInstance);
IVdsDisk_Release(pDisk);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not access VDS Advanced Disk interface: %s", WindowsErrorString());
suprintf("Could not access the requested Disk interface: %s", WindowsErrorString());
}
goto out;
}
IEnumVdsObject_Release(pEnumDisk);
}
IEnumVdsObject_Release(pEnumPack);
}
IEnumVdsObject_Release(pEnum);
out:
return (hr == S_OK);
}
/*
* Delete one partition at offset PartitionOffset, or all partitions if the offset is 0.
*/
BOOL DeletePartition(DWORD DriveIndex, ULONGLONG PartitionOffset, BOOL bSilent)
{
HRESULT hr = S_FALSE;
VDS_PARTITION_PROP* prop_array;
LONG i, prop_array_size;
IVdsAdvancedDisk *pAdvancedDisk;
if (!GetVdsDiskInterface(DriveIndex, &IID_IVdsAdvancedDisk, (void**)&pAdvancedDisk, bSilent))
return FALSE;
// 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) {
suprintf("Deleting partition%s:", (PartitionOffset == 0) ? "s" : "");
// Now go through each partition
for (i = 0; i < prop_array_size; i++) {
if ((PartitionOffset != 0) && (prop_array[i].ullOffset != PartitionOffset))
continue;
suprintf("● 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) {
VDS_SET_ERROR(hr);
suprintf("Could not delete partition: %s", WindowsErrorString());
}
}
} else {
suprintf("No partition to delete on disk");
hr = S_OK;
}
CoTaskMemFree(prop_array);
IVdsAdvancedDisk_Release(pAdvancedDisk);
return (hr == S_OK);
}
/*
* Count on Microsoft for *COMPLETELY CRIPPLING* an API when alledgedly upgrading it...
* As illustrated when you do so with diskpart (which uses VDS behind the scenes), VDS
* simply *DOES NOT* list all the volumes that the system can see, especially compared
* to what mountvol (which uses FindFirstVolume()/FindNextVolume()) and other APIs do.
* Also for reference, if you want to list volumes through WMI in PowerShell:
* Get-WmiObject win32_volume | Format-Table -Property DeviceID,Name,Label,Capacity
*/
BOOL ListVdsVolumes(BOOL bSilent)
{
HRESULT hr = S_FALSE;
ULONG ulFetched;
IVdsServiceLoader* pLoader;
IVdsService* pService;
IEnumVdsObject* pEnum;
IUnknown* pUnk;
// 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) {
VDS_SET_ERROR(hr);
suprintf("Could not create VDS Loader Instance: %s", WindowsErrorString());
goto out;
}
// Load the VDS Service
hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);
IVdsServiceLoader_Release(pLoader);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
suprintf("Could not load VDS Service: %s", WindowsErrorString());
goto out;
}
// Wait for the Service to become ready if needed
hr = IVdsService_WaitForServiceReady(pService);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
suprintf("VDS Service is not ready: %s", WindowsErrorString());
goto out;
}
// Query the VDS Service Providers
hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
IVdsService_Release(pService);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
suprintf("Could not query VDS Service Providers: %s", WindowsErrorString());
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) {
VDS_SET_ERROR(hr);
suprintf("Could not get VDS Provider: %s", WindowsErrorString());
goto out;
}
// Get VDS Software Provider
hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void**)&pSwProvider);
IVdsProvider_Release(pProvider);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
suprintf("Could not get VDS Software Provider: %s", WindowsErrorString());
goto out;
}
// Get VDS Software Provider Packs
hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack);
IVdsSwProvider_Release(pSwProvider);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
suprintf("Could not get VDS Software Provider Packs: %s", WindowsErrorString());
goto out;
}
// Enumerate Provider Packs
while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) {
IVdsPack* pPack;
IEnumVdsObject* pEnumVolume;
IUnknown* pVolumeUnk;
hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void**)&pPack);
IUnknown_Release(pPackUnk);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
suprintf("Could not query VDS Software Provider Pack: %s", WindowsErrorString());
goto out;
}
// Use the pack interface to access the disks
hr = IVdsPack_QueryVolumes(pPack, &pEnumVolume);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
suprintf("Could not query VDS volumes: %s", WindowsErrorString());
goto out;
}
// List volumes
while (IEnumVdsObject_Next(pEnumVolume, 1, &pVolumeUnk, &ulFetched) == S_OK) {
IVdsVolume* pVolume;
IVdsVolumeMF3* pVolumeMF3;
VDS_VOLUME_PROP prop;
LPWSTR* wszPathArray;
ULONG i, ulNumberOfPaths;
// Get the volume interface.
hr = IUnknown_QueryInterface(pVolumeUnk, &IID_IVdsVolume, (void**)&pVolume);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
suprintf("Could not query VDS Volume Interface: %s", WindowsErrorString());
goto out;
}
// Query the partition data, so we can get the start offset, which we need for deletion
hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size);
if (hr == S_OK) {
uprintf("Deleting ALL partition(s) from disk '%S':", diskprop.pwszName);
// Now go through each partition
for (i = 0; i < prop_array_size; i++) {
uprintf("● Partition %d (offset: %lld, size: %s)", prop_array[i].ulPartitionNumber,
prop_array[i].ullOffset, SizeToHumanReadable(prop_array[i].ullSize, FALSE, FALSE));
hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);
if (hr != S_OK) {
r = FALSE;
VDS_SET_ERROR(hr);
uprintf("Could not delete partitions: %s", WindowsErrorString());
}
}
r = TRUE;
} else {
uprintf("No partition to delete on disk '%S'", diskprop.pwszName);
r = TRUE;
// Get the volume properties
hr = IVdsVolume_GetProperties(pVolume, &prop);
if ((hr != S_OK) && (hr != VDS_S_PROPERTIES_INCOMPLETE)) {
VDS_SET_ERROR(hr);
suprintf("Could not query VDS Volume Properties: %s", WindowsErrorString());
goto out;
}
CoTaskMemFree(prop_array);
#if 0
// Issue a Clean while we're at it
HRESULT hr2 = E_FAIL;
ULONG completed;
IVdsAsync* pAsync;
hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, FALSE, FALSE, &pAsync);
while (SUCCEEDED(hr)) {
if (IS_ERROR(FormatStatus)) {
IVdsAsync_Cancel(pAsync);
break;
}
hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);
if (SUCCEEDED(hr)) {
hr = hr2;
if (hr == S_OK)
break;
if (hr == VDS_E_OPERATION_PENDING)
hr = S_OK;
}
Sleep(500);
}
uprintf("FOUND VOLUME: '%S'", prop.pwszName);
CoTaskMemFree(prop.pwszName);
IVdsVolume_Release(pVolume);
// Get the volume MF3 interface.
hr = IUnknown_QueryInterface(pVolumeUnk, &IID_IVdsVolumeMF3, (void**)&pVolumeMF3);
if (hr != S_OK) {
VDS_SET_ERROR(hr);
uprintf("Could not clean disk: %s", WindowsErrorString());
suprintf("Could not query VDS VolumeMF3 Interface: %s", WindowsErrorString());
goto out;
}
#endif
IVdsAdvancedDisk_Release(pAdvancedDisk);
goto out;
// Get the volume properties
hr = IVdsVolumeMF3_QueryVolumeGuidPathnames(pVolumeMF3, &wszPathArray, &ulNumberOfPaths);
if ((hr != S_OK) && (hr != VDS_S_PROPERTIES_INCOMPLETE)) {
VDS_SET_ERROR(hr);
suprintf("Could not query VDS VolumeMF3 GUID PathNames: %s", WindowsErrorString());
goto out;
}
for (i = 0; i < ulNumberOfPaths; i++)
uprintf(" VOL GUID: '%S'", wszPathArray[i]);
CoTaskMemFree(wszPathArray);
IVdsVolume_Release(pVolumeMF3);
IUnknown_Release(pVolumeUnk);
}
IEnumVdsObject_Release(pEnumVolume);
}
IEnumVdsObject_Release(pEnumPack);
}
IEnumVdsObject_Release(pEnum);
out:
if (bNeverFound)
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_PATH_NOT_FOUND;
return r;
return (hr == S_OK);
}
/* Wait for a logical drive to reappear - Used when a drive has just been repartitioned */
BOOL WaitForLogical(DWORD DriveIndex, uint64_t PartitionOffset)
{
@ -1695,7 +1860,6 @@ BOOL RemountVolume(char* drive_name)
* properly reset Windows's cached view of a drive partitioning short of cycling the USB port
* (especially IOCTL_DISK_UPDATE_PROPERTIES is *USELESS*), and therefore the OS will try to
* read the file system data at an old location, even if the partition has just been deleted.
* TODO: We should do something like this in DeletePartitions() too.
*/
static BOOL ClearPartition(HANDLE hDrive, LARGE_INTEGER offset, DWORD size)
{

View File

@ -297,12 +297,14 @@ interface IVdsAsync {
#define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This))
#define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This))
#define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This))
#define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This))
#define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This))
#define IVdsService_Release(This) (This)->lpVtbl->Release(This)
#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 IVdsPack_Release(This) (This)->lpVtbl->Release(This)
#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)
@ -311,6 +313,7 @@ interface IVdsAsync {
#define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync)
#define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)
#define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched)
#define IEnumVdsObject_Release(This) (This)->lpVtbl->Release(This)
#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)
@ -368,7 +371,8 @@ extern uint64_t partition_offset[PI_MAX];
BOOL SetAutoMount(BOOL enable);
BOOL GetAutoMount(BOOL* enabled);
char* GetPhysicalName(DWORD DriveIndex);
BOOL DeletePartitions(DWORD DriveIndex);
BOOL DeletePartition(DWORD DriveIndex, ULONGLONG PartitionOffset, BOOL bSilent);
BOOL ListVdsVolumes(BOOL bSilent);
HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
char* GetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent);
char* AltGetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent);

View File

@ -1747,7 +1747,7 @@ DWORD WINAPI FormatThread(void* param)
// for VDS to be able to delete the partitions that reside on it...
safe_unlockclose(hPhysicalDrive);
PrintInfo(0, MSG_239, lmprintf(MSG_307));
if (!DeletePartitions(DriveIndex)) {
if (!DeletePartition(DriveIndex, 0, FALSE)) {
SetLastError(FormatStatus);
uprintf("Notice: Could not delete partitions: %s", WindowsErrorString());
FormatStatus = 0;

View File

@ -3502,6 +3502,7 @@ relaunch:
&& (msg.wParam == 'T')) {
//extern int TestChecksum(void);
//TestChecksum();
ListVdsVolumes(FALSE);
continue;
}
#endif

View File

@ -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.12.1712"
CAPTION "Rufus 3.12.1713"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -395,8 +395,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,12,1712,0
PRODUCTVERSION 3,12,1712,0
FILEVERSION 3,12,1713,0
PRODUCTVERSION 3,12,1713,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -414,13 +414,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.12.1712"
VALUE "FileVersion", "3.12.1713"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2020 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-3.12.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.12.1712"
VALUE "ProductVersion", "3.12.1713"
END
END
BLOCK "VarFileInfo"