From 415238cbe228654c6d45c034c50b7f7db59a2bff Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Fri, 24 Apr 2020 10:48:45 +0900 Subject: [PATCH 1/2] [SHELL32] Distinguish floppy and removable drives --- dll/win32/shell32/dialogs/drvdefext.cpp | 121 +++++++++++++++++++- dll/win32/shell32/folders/CDrivesFolder.cpp | 16 ++- 2 files changed, 134 insertions(+), 3 deletions(-) diff --git a/dll/win32/shell32/dialogs/drvdefext.cpp b/dll/win32/shell32/dialogs/drvdefext.cpp index f65091f55cc..0a477cec834 100644 --- a/dll/win32/shell32/dialogs/drvdefext.cpp +++ b/dll/win32/shell32/dialogs/drvdefext.cpp @@ -3,6 +3,7 @@ * * Copyright 2005 Johannes Anderwald * Copyright 2012 Rafal Harabien + * Copyright 2020 Katayama Hirofumi MZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +25,10 @@ #define _USE_MATH_DEFINES #include +#define NTOS_MODE_USER +#include +#include + WINE_DEFAULT_DEBUG_CHANNEL(shell); static const GUID GUID_DEVCLASS_DISKDRIVE = {0x4d36e967L, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}; @@ -278,6 +283,115 @@ CDrvDefExt::PaintStaticControls(HWND hwndDlg, LPDRAWITEMSTRUCT pDrawItem) } } +typedef NTSTATUS (NTAPI *FN_NtQueryVolumeInformationFile)(HANDLE, PIO_STATUS_BLOCK, + PVOID, ULONG, FS_INFORMATION_CLASS); + +// https://stackoverflow.com/questions/3098696/get-information-about-disk-drives-result-on-windows7-32-bit-system/3100268#3100268 +static BOOL +GetDriveTypeAndCharacteristics(HANDLE hDevice, DEVICE_TYPE *pDeviceType, ULONG *pCharacteristics) +{ + HMODULE ntdll; + FN_NtQueryVolumeInformationFile pNtQueryVolumeInformationFile; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + FILE_FS_DEVICE_INFORMATION DeviceInfo; + + ntdll = GetModuleHandleA("ntdll"); + if (ntdll == NULL) + return FALSE; + + pNtQueryVolumeInformationFile = + (FN_NtQueryVolumeInformationFile) + GetProcAddress(ntdll, "NtQueryVolumeInformationFile"); + if (pNtQueryVolumeInformationFile == NULL) + return FALSE; + + Status = pNtQueryVolumeInformationFile(hDevice, &IoStatusBlock, + &DeviceInfo, sizeof(DeviceInfo), + FileFsDeviceInformation); + if (Status == NO_ERROR) + { + *pDeviceType = DeviceInfo.DeviceType; + *pCharacteristics = DeviceInfo.Characteristics; + return TRUE; + } + + return FALSE; +} + +BOOL IsDriveFloppyW(LPCWSTR pszDriveRoot) +{ + LPCWSTR RootPath = pszDriveRoot; + WCHAR szRoot[16], szDeviceName[16]; + UINT uType; + HANDLE hDevice; + DEVICE_TYPE DeviceType; + ULONG ulCharacteristics; + BOOL ret; + + lstrcpynW(szRoot, RootPath, _countof(szRoot)); + + if (L'a' <= szRoot[0] && szRoot[0] <= 'z') + { + szRoot[0] += ('A' - 'a'); + } + + if ('A' <= szRoot[0] && szRoot[0] <= L'Z' && + szRoot[1] == L':' && szRoot[2] == 0) + { + // 'C:' --> 'C:\' + szRoot[2] = L'\\'; + szRoot[3] = 0; + } + + if (!PathIsRootW(szRoot)) + { + return FALSE; + } + + uType = GetDriveTypeW(szRoot); + if (uType == DRIVE_REMOVABLE) + { + if (szRoot[0] == L'A' || szRoot[0] == L'B') + return TRUE; + } + else + { + return FALSE; + } + + lstrcpynW(szDeviceName, L"\\\\.\\", _countof(szDeviceName)); + szDeviceName[4] = szRoot[0]; + szDeviceName[5] = L':'; + szDeviceName[6] = UNICODE_NULL; + + hDevice = CreateFileW(szDeviceName, FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + ret = FALSE; + if (GetDriveTypeAndCharacteristics(hDevice, &DeviceType, &ulCharacteristics)) + { + if ((ulCharacteristics & FILE_FLOPPY_DISKETTE) == FILE_FLOPPY_DISKETTE) + ret = TRUE; + } + + CloseHandle(hDevice); + + return ret; +} + +BOOL IsDriveFloppyA(LPCSTR pszDriveRoot) +{ + WCHAR szRoot[8]; + MultiByteToWideChar(CP_ACP, 0, pszDriveRoot, -1, szRoot, _countof(szRoot)); + return IsDriveFloppyW(szRoot); +} + VOID CDrvDefExt::InitGeneralPage(HWND hwndDlg) { @@ -304,7 +418,12 @@ CDrvDefExt::InitGeneralPage(HWND hwndDlg) UINT IconId, TypeStrId = 0; switch (DriveType) { - case DRIVE_REMOVABLE: IconId = IDI_SHELL_3_14_FLOPPY; break; + case DRIVE_REMOVABLE: + if (IsDriveFloppyW(m_wszDrive)) + IconId = IDI_SHELL_3_14_FLOPPY; + else + IconId = IDI_SHELL_REMOVEABLE; + break; case DRIVE_CDROM: IconId = IDI_SHELL_CDROM; TypeStrId = IDS_DRIVE_CDROM; break; case DRIVE_REMOTE: IconId = IDI_SHELL_NETDRIVE; TypeStrId = IDS_DRIVE_NETWORK; break; case DRIVE_RAMDISK: IconId = IDI_SHELL_RAMDISK; break; diff --git a/dll/win32/shell32/folders/CDrivesFolder.cpp b/dll/win32/shell32/folders/CDrivesFolder.cpp index 53c1b94dbaa..482225ab607 100644 --- a/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -449,6 +449,8 @@ getIconLocationForDrive(IShellFolder *psf, PCITEMID_CHILD pidl, UINT uFlags, return E_FAIL; } +BOOL IsDriveFloppyA(LPCSTR pszDriveRoot); + HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut) { CComPtr initIcon; @@ -476,7 +478,14 @@ HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl } else { - icon_idx = iDriveIconIds[DriveType]; + if (DriveType == DRIVE_REMOVABLE && !IsDriveFloppyA(pszDrive)) + { + icon_idx = IDI_SHELL_REMOVEABLE; + } + else + { + icon_idx = iDriveIconIds[DriveType]; + } initIcon->SetNormalIcon(swShell32Name, -icon_idx); } @@ -1117,7 +1126,10 @@ HRESULT WINAPI CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, S hr = SHSetStrRet(&psd->str, ""); break; case 2: /* type */ - hr = SHSetStrRet(&psd->str, iDriveTypeIds[DriveType]); + if (DriveType == DRIVE_REMOVABLE && !IsDriveFloppyA(pszDrive)) + hr = SHSetStrRet(&psd->str, IDS_DRIVE_REMOVABLE); + else + hr = SHSetStrRet(&psd->str, iDriveTypeIds[DriveType]); break; case 3: /* total size */ case 4: /* free size */ From 81cc35b716643a954bd5f592ab12042bc6dac4b1 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Fri, 24 Apr 2020 18:37:42 +0900 Subject: [PATCH 2/2] direct call --- dll/win32/shell32/dialogs/drvdefext.cpp | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/dll/win32/shell32/dialogs/drvdefext.cpp b/dll/win32/shell32/dialogs/drvdefext.cpp index 0a477cec834..82e8764e835 100644 --- a/dll/win32/shell32/dialogs/drvdefext.cpp +++ b/dll/win32/shell32/dialogs/drvdefext.cpp @@ -283,32 +283,17 @@ CDrvDefExt::PaintStaticControls(HWND hwndDlg, LPDRAWITEMSTRUCT pDrawItem) } } -typedef NTSTATUS (NTAPI *FN_NtQueryVolumeInformationFile)(HANDLE, PIO_STATUS_BLOCK, - PVOID, ULONG, FS_INFORMATION_CLASS); - // https://stackoverflow.com/questions/3098696/get-information-about-disk-drives-result-on-windows7-32-bit-system/3100268#3100268 static BOOL GetDriveTypeAndCharacteristics(HANDLE hDevice, DEVICE_TYPE *pDeviceType, ULONG *pCharacteristics) { - HMODULE ntdll; - FN_NtQueryVolumeInformationFile pNtQueryVolumeInformationFile; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; FILE_FS_DEVICE_INFORMATION DeviceInfo; - ntdll = GetModuleHandleA("ntdll"); - if (ntdll == NULL) - return FALSE; - - pNtQueryVolumeInformationFile = - (FN_NtQueryVolumeInformationFile) - GetProcAddress(ntdll, "NtQueryVolumeInformationFile"); - if (pNtQueryVolumeInformationFile == NULL) - return FALSE; - - Status = pNtQueryVolumeInformationFile(hDevice, &IoStatusBlock, - &DeviceInfo, sizeof(DeviceInfo), - FileFsDeviceInformation); + Status = NtQueryVolumeInformationFile(hDevice, &IoStatusBlock, + &DeviceInfo, sizeof(DeviceInfo), + FileFsDeviceInformation); if (Status == NO_ERROR) { *pDeviceType = DeviceInfo.DeviceType;