From 36693d2144d3da3d6d83ab6979c66149d0aa2ae4 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Fri, 20 Dec 2013 18:32:10 +0000 Subject: [PATCH] [core] detect memory cards in card readers * Also remove drives with no media from the list * Closes #18 --- src/drive.c | 17 +++++++++++++++ src/format.c | 2 +- src/localization.c | 1 - src/rufus.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-- src/rufus.h | 2 ++ src/rufus.rc | 10 ++++----- 6 files changed, 75 insertions(+), 9 deletions(-) diff --git a/src/drive.c b/src/drive.c index 0d0c63ea..871e1cdd 100644 --- a/src/drive.c +++ b/src/drive.c @@ -450,6 +450,23 @@ uint64_t GetDriveSize(DWORD DriveIndex) return DiskGeometry->DiskSize.QuadPart; } +/* + * GET_DRIVE_GEOMETRY is used to tell if there is an actual media + */ +BOOL IsMediaPresent(DWORD DriveIndex) +{ + BOOL r; + HANDLE hPhysical; + DWORD size; + BYTE geometry[128]; + + hPhysical = GetPhysicalHandle(DriveIndex, FALSE, FALSE); + r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, + NULL, 0, geometry, sizeof(geometry), &size, NULL) || (size <= 0); + safe_closehandle(hPhysical); + return r; +} + /* * Fill the drive properties (size, FS, etc) */ diff --git a/src/format.c b/src/format.c index 5aebde8d..1961e393 100644 --- a/src/format.c +++ b/src/format.c @@ -1243,7 +1243,7 @@ DWORD WINAPI FormatThread(LPVOID param) // Try to ensure that all messages from Format and Checkdisk, which we report in the log, will be in English pfSetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); if (PRIMARYLANGID(pfGetThreadUILanguage()) != LANG_ENGLISH) - uprintf("Note: the formatting thread could not be set to English"); + uprintf("Note: some formatting messages may still be localized"); PrintStatus(0, TRUE, MSG_225); hPhysicalDrive = GetPhysicalHandle(DriveIndex, TRUE, TRUE); diff --git a/src/localization.c b/src/localization.c index e685ebe0..01e15573 100644 --- a/src/localization.c +++ b/src/localization.c @@ -134,7 +134,6 @@ static BOOL htab_create(uint32_t nel) nel += 2; htab_size = nel; - uprintf("localization: using %d entries hash table\n", nel); htab_filled = 0; // allocate memory and zero out. diff --git a/src/rufus.c b/src/rufus.c index 8c144025..71e71c07 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -65,7 +66,7 @@ #define DBT_CUSTOMEVENT 0x8006 #endif -// MinGW fails to link those +// MinGW fails to link those... typedef HIMAGELIST (WINAPI *ImageList_Create_t)( int cx, int cy, @@ -86,6 +87,25 @@ struct { UINT uAlign; } bi_iso = {0}, bi_up = {0}, bi_down = {0}, bi_lang = {0}; // BUTTON_IMAGELIST +// ...and MinGW doesn't know these. +typedef struct +{ + LPCITEMIDLIST pidl; + BOOL fRecursive; +} MY_SHChangeNotifyEntry; + +typedef BOOL (WINAPI *SHChangeNotifyDeregister_t)( + ULONG ulID +); +typedef ULONG (WINAPI *SHChangeNotifyRegister_t)( + HWND hwnd, + int fSources, + LONG fEvents, + UINT wMsg, + int cEntries, + const MY_SHChangeNotifyEntry *pshcne +); + const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "UDF", "exFAT" }; // Number of steps for each FS for FCC_STRUCTURE_PROGRESS const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10 }; @@ -745,6 +765,13 @@ static BOOL GetUSBDevices(DWORD devnum) } drive_index = device_number.DeviceNumber + DRIVE_INDEX_MIN; + if (!IsMediaPresent(drive_index)) { + uprintf("Device eliminated because it appears to contain no media\n"); + safe_closehandle(hDrive); + safe_free(devint_detail_data); + break; + } + if (GetDriveLabel(drive_index, &drive_letter, &label)) { if ((!enable_HDDs) && ((score = IsHDD(drive_index, vid, pid, buffer)) > 0)) { uprintf("Device eliminated because it was detected as an USB Hard Drive (score %d > 0)\n", score); @@ -1512,10 +1539,18 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA char tmp[128]; static UINT uBootChecked = BST_CHECKED, uQFChecked; static BOOL first_log_display = TRUE, user_changed_label = FALSE; + static ULONG ulRegister = 0; + static LPITEMIDLIST pidlDesktop = NULL; + static MY_SHChangeNotifyEntry NotifyEntry; loc_cmd* lcmd = NULL; + PF_DECL(SHChangeNotifyRegister); + PF_DECL(SHChangeNotifyDeregister); switch (message) { + case UM_MEDIA_CHANGE: + wParam = DBT_CUSTOMEVENT; + // Fall through case WM_DEVICECHANGE: // The Windows hotplug subsystem sucks. Among other things, if you insert a GPT partitioned // USB drive with zero partitions, the only device messages you will get are a stream of @@ -1528,7 +1563,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA switch (wParam) { case DBT_DEVICEARRIVAL: case DBT_DEVICEREMOVECOMPLETE: - case DBT_CUSTOMEVENT: // This last event is sent by our timer refresh function + case DBT_CUSTOMEVENT: // Sent by our timer refresh function or for card reader media change LastRefresh = GetTickCount(); // Don't care about 49.7 days rollback of GetTickCount() KillTimer(hMainDialog, TID_REFRESH_TIMER); GetUSBDevices((DWORD)ComboBox_GetItemData(hDeviceList, ComboBox_GetCurSel(hDeviceList))); @@ -1549,6 +1584,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA break; case WM_INITDIALOG: + PF_INIT(SHChangeNotifyRegister, shell32); apply_localization(IDD_DIALOG, hDlg); SetUpdateCheck(); advanced_mode = TRUE; @@ -1559,6 +1595,15 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA InitDialog(hDlg); GetUSBDevices(0); CheckForUpdates(FALSE); + // Register MEDIA_INSERTED/MEDIA_REMOVED notifications for card readers + if ((pfSHChangeNotifyRegister != NULL) && (SUCCEEDED(SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, &pidlDesktop)))) { + NotifyEntry.pidl = pidlDesktop; + NotifyEntry.fRecursive = TRUE; + // NB: The following only works if the media is already formatted. + // If you insert a blank card, notifications will not be sent... :( + ulRegister = pfSHChangeNotifyRegister(hDlg, 0x0001|0x0002|0x8000, + SHCNE_MEDIAINSERTED|SHCNE_MEDIAREMOVED, UM_MEDIA_CHANGE, 1, &NotifyEntry); + } PostMessage(hMainDialog, UM_ISO_CREATE, 0, 0); return (INT_PTR)TRUE; @@ -1600,6 +1645,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA switch(LOWORD(wParam)) { case IDOK: // close application case IDCANCEL: + PF_INIT(SHChangeNotifyDeregister, shell32); EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), FALSE); EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE); if (format_thid != NULL) { @@ -1622,6 +1668,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA } return (INT_PTR)TRUE; } + if ((pfSHChangeNotifyDeregister != NULL) && (ulRegister != 0)) + pfSHChangeNotifyDeregister(ulRegister); PostQuitMessage(0); StrArrayDestroy(&DriveID); StrArrayDestroy(&DriveLabel); diff --git a/src/rufus.h b/src/rufus.h index cc5c723e..1592b542 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -109,6 +109,7 @@ extern void _uprintf(const char *format, ...); /* Custom Windows messages */ enum user_message_type { UM_FORMAT_COMPLETED = WM_APP, + UM_MEDIA_CHANGE, // TODO: relabel "ISO" to a more generic "progress" UM_ISO_CREATE, UM_ISO_INIT, @@ -329,6 +330,7 @@ extern BOOL DeletePartitions(HANDLE hDrive); extern const char* GetPartitionType(BYTE Type); extern BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSystemNameSize); extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label); +extern BOOL IsMediaPresent(DWORD DriveIndex); extern BOOL MountVolume(char* drive_name, char *drive_guid); extern BOOL UnmountVolume(HANDLE hDrive); extern BOOL RemountVolume(char* drive_name); diff --git a/src/rufus.rc b/src/rufus.rc index 72125ea8..95ea958c 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.4.2.359" +CAPTION "Rufus v1.4.2.360" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,291,50,14 @@ -288,8 +288,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,2,359 - PRODUCTVERSION 1,4,2,359 + FILEVERSION 1,4,2,360 + PRODUCTVERSION 1,4,2,360 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -306,13 +306,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.4.2.359" + VALUE "FileVersion", "1.4.2.360" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2013 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.4.2.359" + VALUE "ProductVersion", "1.4.2.360" END END BLOCK "VarFileInfo"