[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:
Pete Batard 2021-01-15 17:50:57 +00:00
parent 3056d54cc1
commit 20b8a84595
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
5 changed files with 89 additions and 11 deletions

View File

@ -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

View File

@ -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
@ -54,6 +54,9 @@
#define FILE_FLOPPY_DISKETTE 0x00000004
#define VDS_RESCAN_REFRESH 0x00000001
#define VDS_RESCAN_REENUMERATE 0x00000002
#define VDS_SET_ERROR(hr) do { if (hr != S_OK) { SetLastError(hr); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE; } } while(0)
#if !defined(__MINGW32__)
@ -373,6 +376,7 @@ BOOL GetAutoMount(BOOL* enabled);
char* GetPhysicalName(DWORD DriveIndex);
BOOL DeletePartition(DWORD DriveIndex, ULONGLONG PartitionOffset, BOOL bSilent);
BOOL ListVdsVolumes(BOOL bSilent);
BOOL VdsRescan(DWORD dwRescanType, DWORD dwSleepTime, 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

@ -104,7 +104,9 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
inode.i_mode = LINUX_S_IFLNK | 0777;
inode.i_uid = inode.i_gid = 0;
inode.i_links_count = 1;
ext2fs_inode_size_set(fs, &inode, target_len);
retval = ext2fs_inode_size_set(fs, &inode, target_len);
if (retval)
goto cleanup;
/* The time fields are set by ext2fs_write_new_inode() */
inlinelink = !fastlink && ext2fs_has_feature_inline_data(fs->super);

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Formatting 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
@ -2181,6 +2181,7 @@ DWORD WINAPI FormatThread(void* param)
}
out:
VdsRescan(VDS_RESCAN_REFRESH, 0, TRUE);
safe_free(volume_name);
safe_free(buffer);
safe_closehandle(hSourceImage);

View File

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