mirror of
https://github.com/pbatard/rufus.git
synced 2025-06-06 17:41:36 -04:00
[core] fix potential "loss" of disk after writing Ubuntu 20.10 in DD mode
* Due to the partition gymnastic that is required by the hack that is ISOHybrid, some ISOHybrid images that are written in DD mode, such as Ubuntu 20.10, may result in Windows somehow "losing" the target disk from some of its listings. * This "removal" can be seen for instance if you have diskpart already open and issue 'list disk' after Rufus 3.13 completed its image writing. * In the worst case scenario, Windows may flat out refuse to access the disk at the sector level be it in diskpart or disk manager, which forces ones to clear the partition tables on Linux or some other OS to be able to "recover" the disk. * This appears to be mostly due to Windows VDS cache (which Microsoft assures should be able to do a proper job of refreshing itself on its own, in the same stride as they also feel the need to introduce IVdsService::Refresh whose sole purpose appears to work around a limitation that Microsoft knows exists) not being in sync with the actual disk layout. * So we now add calls to VDS layout refresh where needed, to work around the issue. * Also fix an ext2fs Coverity warning.
This commit is contained in:
parent
3056d54cc1
commit
20b8a84595
5 changed files with 89 additions and 11 deletions
77
src/drive.c
77
src/drive.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Rufus: The Reliable USB Formatting Utility
|
||||
* Drive access function calls
|
||||
* Copyright © 2011-2020 Pete Batard <pete@akeo.ie>
|
||||
* Copyright © 2011-2021 Pete Batard <pete@akeo.ie>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -649,6 +649,7 @@ static BOOL GetVdsDiskInterface(DWORD DriveIndex, const IID* InterfaceIID, void*
|
|||
}
|
||||
|
||||
// Check if we are on the target disk
|
||||
// uprintf("GetVdsDiskInterface: Seeking %S found %S", wPhysicalName, prop.pwszName);
|
||||
hr = (HRESULT)_wcsicmp(wPhysicalName, prop.pwszName);
|
||||
CoTaskMemFree(prop.pwszName);
|
||||
if (hr != S_OK) {
|
||||
|
@ -676,6 +677,71 @@ out:
|
|||
return (hr == S_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke IVdsService::Refresh() and/or IVdsService::Reenumerate() to force a
|
||||
* rescan of the VDS disks. This can become necessary after writing an image
|
||||
* such as Ubuntu 20.10, as Windows may "lose" the active disk otherwise...
|
||||
*/
|
||||
BOOL VdsRescan(DWORD dwRescanType, DWORD dwSleepTime, BOOL bSilent)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
HRESULT hr = S_FALSE;
|
||||
IVdsServiceLoader* pLoader;
|
||||
IVdsService* pService;
|
||||
|
||||
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));
|
||||
|
||||
hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
|
||||
&IID_IVdsServiceLoader, (void**)&pLoader);
|
||||
if (hr != S_OK) {
|
||||
suprintf("Could not create VDS Loader Instance: %s", VdsErrorString(hr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);
|
||||
IVdsServiceLoader_Release(pLoader);
|
||||
if (hr != S_OK) {
|
||||
suprintf("Could not load VDS Service: %s", VdsErrorString(hr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IVdsService_WaitForServiceReady(pService);
|
||||
if (hr != S_OK) {
|
||||
suprintf("VDS Service is not ready: %s", VdsErrorString(hr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/vds/nf-vds-ivdsservice-refresh
|
||||
// This method synchronizes the disk layout to the layout known to the disk driver.
|
||||
// It does not force the driver to read the layout from the disk.
|
||||
// Additionally, this method refreshes the view of all objects in the VDS cache.
|
||||
if (dwRescanType & VDS_RESCAN_REFRESH) {
|
||||
hr = IVdsService_Refresh(pService);
|
||||
if (hr != S_OK) {
|
||||
suprintf("VDS Refresh failed: %s", VdsErrorString(hr));
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/vds/nf-vds-ivdsservice-reenumerate
|
||||
// This method returns immediately after a bus rescan request is issued.
|
||||
// The operation might be incomplete when the method returns.
|
||||
if (dwRescanType & VDS_RESCAN_REENUMERATE) {
|
||||
hr = IVdsService_Reenumerate(pService);
|
||||
if (hr != S_OK) {
|
||||
suprintf("VDS Re-enumeration failed: %s", VdsErrorString(hr));
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (dwSleepTime != 0)
|
||||
Sleep(dwSleepTime);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete one partition at offset PartitionOffset, or all partitions if the offset is 0.
|
||||
*/
|
||||
|
@ -689,8 +755,13 @@ BOOL DeletePartition(DWORD DriveIndex, ULONGLONG PartitionOffset, BOOL bSilent)
|
|||
if (!GetVdsDiskInterface(DriveIndex, &IID_IVdsAdvancedDisk, (void**)&pAdvancedDisk, bSilent))
|
||||
return FALSE;
|
||||
if (pAdvancedDisk == NULL) {
|
||||
suprintf("No partition to delete on disk");
|
||||
return TRUE;
|
||||
suprintf("Looks like Windows has \"lost\" our disk - Forcing a VDS rescan...");
|
||||
VdsRescan(VDS_RESCAN_REFRESH | VDS_RESCAN_REENUMERATE, 1000, bSilent);
|
||||
if (!GetVdsDiskInterface(DriveIndex, &IID_IVdsAdvancedDisk, (void**)&pAdvancedDisk, bSilent) ||
|
||||
(pAdvancedDisk == NULL)) {
|
||||
suprintf("Could not locate disk - Aborting.");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Query the partition data, so we can get the start offset, which we need for deletion
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue