[core] work around a Windows bug where GetVolumePathNamesForVolumeName() can return the wrong drive letter

* A user is reporting that, on one of their platforms, Rufus is writing to the wrong target during the file-copy
  phase and using their existing Y: local drive instead of the drive associated to the USB, despite the fact
  that Rufus is passing the right volume name to GetVolumePathNamesForVolumeName().

* Here's the PowerShell wmic output, confirming that the volume GUID obtained by Rufus is the right one:

  DriveLetter : Y:
  DeviceId    : \\?\Volume{000349b1-17d0-69f6-c13f-f31162930600}\
  Capacity    : 118540464128
  FileSystem  : NTFS
  Label       : Y-DISK

  DriveLetter : H:
  DeviceId    : \\?\Volume{b150ff4a-d62b-11ea-86e3-f49634660e54}\
  Capacity    : 15791824896
  FileSystem  : FAT32
  Label       : ADATA16GB

* And here's the Rufus log demonstrating that GetVolumePathNamesForVolumeName() is returning the *WRONG* letter:

  Found volume \\?\Volume{b150ff4a-d62b-11ea-86e3-f49634660e54}\
  \\?\Volume{b150ff4a-d62b-11ea-86e3-f49634660e54}\ is already mounted as Y: instead of H: - Will now use this target instead...

* The last line shows, without the shadow of a doubt, that we did feed "\\?\Volume{b150ff4a-d62b-11ea-86e3-f49634660e54}\" to
  GetVolumePathNamesForVolumeName() and that this API call was successful (returned a non zero size) but ultimately returned
  the wrong letter (Y: instead of H:)...

* Therefore, Windows is BUGGY and the use of GetVolumePathNamesForVolumeName() must be avoided.
This commit is contained in:
Pete Batard 2020-08-13 14:49:34 +01:00
parent c2017ad659
commit ba406843f4
No known key found for this signature in database
GPG key ID: 38E0CF5E69EDD671
4 changed files with 17 additions and 9 deletions

View file

@ -1522,12 +1522,19 @@ BOOL MountVolume(char* drive_name, char *volume_name)
{
char mounted_guid[52];
char mounted_letter[27] = { 0 };
#if defined(WINDOWS_IS_NOT_BUGGY)
DWORD size;
#endif
if ((drive_name == NULL) || (volume_name == NULL) || (drive_name[0] == '?') ||
(strncmp(volume_name, groot_name, groot_len) == 0))
return FALSE;
// Great: Windows has a *MAJOR BUG* whereas, in some circumstances, GetVolumePathNamesForVolumeName()
// can return the *WRONG* drive letter. And yes, we validated that this is *NOT* an issue like stack
// or buffer corruption and whatnot. It *IS* a Windows bug. So just drop the idea of updating the
// drive letter if already mounted and use the passed target always.
#if defined(WINDOWS_IS_NOT_BUGGY)
// Windows may already have the volume mounted but under a different letter.
// If that is the case, update drive_name to that letter.
if ( (GetVolumePathNamesForVolumeNameA(volume_name, mounted_letter, sizeof(mounted_letter), &size))
@ -1537,6 +1544,7 @@ BOOL MountVolume(char* drive_name, char *volume_name)
drive_name[0] = mounted_letter[0];
return TRUE;
}
#endif
if (!SetVolumeMountPointA(drive_name, volume_name)) {
if (GetLastError() == ERROR_DIR_NOT_EMPTY) {