From 1f3cb13fb97e618b53e55db0f455fe7259694326 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Wed, 6 May 2020 00:35:01 +0900 Subject: [PATCH] [SHELL32] Distinguish floppy and removable drives (#2645) Distinguish floppy drive and non-floppy removable drive in icon and description. CORE-10221 --- dll/win32/shell32/dialogs/drvdefext.cpp | 106 +++++++++++++++++++- dll/win32/shell32/folders/CDrivesFolder.cpp | 16 ++- 2 files changed, 119 insertions(+), 3 deletions(-) diff --git a/dll/win32/shell32/dialogs/drvdefext.cpp b/dll/win32/shell32/dialogs/drvdefext.cpp index f65091f55cc..82e8764e835 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,100 @@ CDrvDefExt::PaintStaticControls(HWND hwndDlg, LPDRAWITEMSTRUCT pDrawItem) } } +// 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) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + FILE_FS_DEVICE_INFORMATION DeviceInfo; + + Status = NtQueryVolumeInformationFile(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 +403,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 */