Windows: in case of mounting system favorites, call driver to get list of drives instead of using SetupAPI in order to fix some rare issues where some disks were not detected at boot.

This commit is contained in:
Mounir IDRASSI 2017-07-19 11:25:25 +02:00
parent d78a3d0273
commit fe26ed8a5d
No known key found for this signature in database
GPG Key ID: DD0C382D5FCFB8FC
3 changed files with 106 additions and 87 deletions

View File

@ -11866,8 +11866,11 @@ void AddDeviceToList (std::vector<HostDevice>& devices, int devNumber, int partN
devices.push_back (device); devices.push_back (device);
} }
std::vector <HostDevice> GetHostRawDeviceList () std::vector <HostDevice> GetHostRawDeviceList (bool bFromService)
{ {
if (bFromService)
return GetAvailableHostDevices (true, false, true, true);
std::vector <HostDevice> list; std::vector <HostDevice> list;
HDEVINFO diskClassDevices; HDEVINFO diskClassDevices;
GUID diskClassDeviceInterfaceGuid = GUID_DEVINTERFACE_DISK; GUID diskClassDeviceInterfaceGuid = GUID_DEVINTERFACE_DISK;
@ -11980,7 +11983,7 @@ bool CompareDeviceList (const std::vector<HostDevice>& list1, const std::vector<
return true; return true;
} }
void UpdateMountableHostDeviceList () void UpdateMountableHostDeviceList (bool bFromService)
{ {
ByteArray buffer(4096); ByteArray buffer(4096);
DWORD bytesReturned; DWORD bytesReturned;
@ -11989,7 +11992,7 @@ void UpdateMountableHostDeviceList ()
EnterCriticalSection (&csMountableDevices); EnterCriticalSection (&csMountableDevices);
finally_do ({ LeaveCriticalSection (&csMountableDevices); }); finally_do ({ LeaveCriticalSection (&csMountableDevices); });
std::vector<HostDevice> newList = GetHostRawDeviceList (); std::vector<HostDevice> newList = GetHostRawDeviceList (bFromService);
std::map<DWORD, bool> existingDevicesMap; std::map<DWORD, bool> existingDevicesMap;
if (CompareDeviceList (newList, rawHostDeviceList)) if (CompareDeviceList (newList, rawHostDeviceList))
@ -12032,104 +12035,120 @@ void UpdateMountableHostDeviceList ()
if (existingDevicesMap[It->SystemNumber]) if (existingDevicesMap[It->SystemNumber])
continue; continue;
HANDLE disk = CreateFile( It->Path.c_str(), if (bFromService)
0, {
FILE_SHARE_READ | FILE_SHARE_WRITE, if (It->Partitions.empty())
NULL, mountableDevices.push_back (*It);
OPEN_EXISTING, else
0,
NULL );
if ( INVALID_HANDLE_VALUE != disk)
{
bool bIsDynamic = false;
bool bHasPartition = false;
if (DeviceIoControl(
disk,
IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
NULL,
0,
(LPVOID) buffer.data(),
(DWORD) buffer.size(),
(LPDWORD) &bytesReturned,
NULL) && (bytesReturned >= sizeof (DRIVE_LAYOUT_INFORMATION_EX)))
{ {
PDRIVE_LAYOUT_INFORMATION_EX layout = (PDRIVE_LAYOUT_INFORMATION_EX) buffer.data(); for (std::vector<HostDevice>::iterator partIt = It->Partitions.begin(); partIt != It->Partitions.end(); partIt++)
// sanity checks
if (layout->PartitionCount <= 256)
{ {
for (DWORD i = 0; i < layout->PartitionCount; i++) if (!partIt->ContainsSystem && !partIt->HasUnencryptedFilesystem)
mountableDevices.push_back (*partIt);
}
}
}
else
{
HANDLE disk = CreateFile( It->Path.c_str(),
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( INVALID_HANDLE_VALUE != disk)
{
bool bIsDynamic = false;
bool bHasPartition = false;
if (DeviceIoControl(
disk,
IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
NULL,
0,
(LPVOID) buffer.data(),
(DWORD) buffer.size(),
(LPDWORD) &bytesReturned,
NULL) && (bytesReturned >= sizeof (DRIVE_LAYOUT_INFORMATION_EX)))
{
PDRIVE_LAYOUT_INFORMATION_EX layout = (PDRIVE_LAYOUT_INFORMATION_EX) buffer.data();
// sanity checks
if (layout->PartitionCount <= 256)
{ {
if (layout->PartitionEntry[i].PartitionStyle == PARTITION_STYLE_MBR) for (DWORD i = 0; i < layout->PartitionCount; i++)
{ {
if (layout->PartitionEntry[i].Mbr.PartitionType == 0) if (layout->PartitionEntry[i].PartitionStyle == PARTITION_STYLE_MBR)
continue;
bHasPartition = true;
/* skip dynamic volume */
if (layout->PartitionEntry[i].Mbr.PartitionType == PARTITION_LDM)
{ {
bIsDynamic = true; if (layout->PartitionEntry[i].Mbr.PartitionType == 0)
/* remove any partition that may have been added */ continue;
while (!mountableDevices.empty() && (mountableDevices.back().SystemNumber == It->SystemNumber))
mountableDevices.pop_back (); bHasPartition = true;
break;
/* skip dynamic volume */
if (layout->PartitionEntry[i].Mbr.PartitionType == PARTITION_LDM)
{
bIsDynamic = true;
/* remove any partition that may have been added */
while (!mountableDevices.empty() && (mountableDevices.back().SystemNumber == It->SystemNumber))
mountableDevices.pop_back ();
break;
}
} }
}
if (layout->PartitionEntry[i].PartitionStyle == PARTITION_STYLE_GPT) if (layout->PartitionEntry[i].PartitionStyle == PARTITION_STYLE_GPT)
{
if (IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_ENTRY_UNUSED_GUID))
continue;
bHasPartition = true;
/* skip dynamic volume */
if ( IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_LDM_METADATA_GUID)
|| IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_LDM_DATA_GUID)
)
{ {
bIsDynamic = true; if (IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_ENTRY_UNUSED_GUID))
/* remove any partition that may have been added */ continue;
while (!mountableDevices.empty() && (mountableDevices.back().SystemNumber == It->SystemNumber))
mountableDevices.pop_back ();
break;
}
}
WCHAR path[MAX_PATH]; bHasPartition = true;
StringCbPrintfW (path, sizeof(path), L"\\\\?\\GLOBALROOT\\Device\\Harddisk%d\\Partition%d", It->SystemNumber, layout->PartitionEntry[i].PartitionNumber);
HANDLE handle = CreateFile( path, /* skip dynamic volume */
0, if ( IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_LDM_METADATA_GUID)
FILE_SHARE_READ | FILE_SHARE_WRITE, || IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_LDM_DATA_GUID)
NULL, )
OPEN_EXISTING, {
0, bIsDynamic = true;
NULL ); /* remove any partition that may have been added */
if ((handle != INVALID_HANDLE_VALUE) || (GetLastError () == ERROR_ACCESS_DENIED)) while (!mountableDevices.empty() && (mountableDevices.back().SystemNumber == It->SystemNumber))
{ mountableDevices.pop_back ();
AddDeviceToList (mountableDevices, It->SystemNumber, layout->PartitionEntry[i].PartitionNumber); break;
if (handle != INVALID_HANDLE_VALUE) }
CloseHandle (handle); }
WCHAR path[MAX_PATH];
StringCbPrintfW (path, sizeof(path), L"\\\\?\\GLOBALROOT\\Device\\Harddisk%d\\Partition%d", It->SystemNumber, layout->PartitionEntry[i].PartitionNumber);
HANDLE handle = CreateFile( path,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ((handle != INVALID_HANDLE_VALUE) || (GetLastError () == ERROR_ACCESS_DENIED))
{
AddDeviceToList (mountableDevices, It->SystemNumber, layout->PartitionEntry[i].PartitionNumber);
if (handle != INVALID_HANDLE_VALUE)
CloseHandle (handle);
}
} }
} }
} }
if (bIsDynamic)
dynamicVolumesPresent = true;
if (!bHasPartition)
AddDeviceToList (mountableDevices, It->SystemNumber, 0);
CloseHandle (disk);
} }
if (bIsDynamic)
dynamicVolumesPresent = true;
if (!bHasPartition)
AddDeviceToList (mountableDevices, It->SystemNumber, 0);
CloseHandle (disk);
} }
} }
rawHostDeviceList = newList; rawHostDeviceList = newList;
// Starting from Vista, Windows does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices // Starting from Vista, Windows does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices
if (dynamicVolumesPresent && (CurrentOSMajor >= 6)) if (!bFromService && dynamicVolumesPresent && (CurrentOSMajor >= 6))
{ {
for (int devNumber = 0; devNumber < 256; devNumber++) for (int devNumber = 0; devNumber < 256; devNumber++)
{ {

View File

@ -626,7 +626,7 @@ inline std::wstring AppendSrcPos (const wchar_t* msg, const char* srcPos)
{ {
return std::wstring (msg? msg : L"") + L"\n\nSource: " + SingleStringToWide (srcPos); return std::wstring (msg? msg : L"") + L"\n\nSource: " + SingleStringToWide (srcPos);
} }
void UpdateMountableHostDeviceList (); void UpdateMountableHostDeviceList (bool bFromService);
INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text); INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text);
// Display a wait dialog while calling the provided callback with the given parameter // Display a wait dialog while calling the provided callback with the given parameter

View File

@ -495,7 +495,7 @@ static void InitMainDialog (HWND hwndDlg)
} }
// initialize the list of devices available for mounting as early as possible // initialize the list of devices available for mounting as early as possible
UpdateMountableHostDeviceList (); UpdateMountableHostDeviceList (false);
// Resize the logo bitmap if the user has a non-default DPI // Resize the logo bitmap if the user has a non-default DPI
if (ScreenDPI != USER_DEFAULT_SCREEN_DPI if (ScreenDPI != USER_DEFAULT_SCREEN_DPI
@ -7119,7 +7119,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
{ {
if (wParam == TIMER_ID_UPDATE_DEVICE_LIST) if (wParam == TIMER_ID_UPDATE_DEVICE_LIST)
{ {
UpdateMountableHostDeviceList (); UpdateMountableHostDeviceList (false);
} }
else else
{ {
@ -9168,7 +9168,7 @@ static VOID WINAPI SystemFavoritesServiceMain (DWORD argc, LPTSTR *argv)
SystemFavoritesServiceLogInfo (wstring (L"Initializing list of host devices")); SystemFavoritesServiceLogInfo (wstring (L"Initializing list of host devices"));
// initialize the list of devices available for mounting as early as possible // initialize the list of devices available for mounting as early as possible
UpdateMountableHostDeviceList (); UpdateMountableHostDeviceList (true);
SystemFavoritesServiceLogInfo (wstring (L"Starting System Favorites mounting process")); SystemFavoritesServiceLogInfo (wstring (L"Starting System Favorites mounting process"));
@ -9702,7 +9702,7 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO
Sleep (5000); Sleep (5000);
SystemFavoritesServiceLogInfo (wstring (L"Updating list of host devices")); SystemFavoritesServiceLogInfo (wstring (L"Updating list of host devices"));
UpdateMountableHostDeviceList (); UpdateMountableHostDeviceList (true);
SystemFavoritesServiceLogInfo (wstring (L"Trying to mount skipped system favorites")); SystemFavoritesServiceLogInfo (wstring (L"Trying to mount skipped system favorites"));