From e041eea1df3070cf5c9595f3e495a7551d9894f3 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Thu, 17 Nov 2011 01:43:06 +0000 Subject: [PATCH] [enum] populate the device list --- .msvc/usbdos_2010.vcxproj | 8 +- usbdos.c | 224 +++++++++++++++++++++++++++++++++++++- usbdos.h | 24 ++-- 3 files changed, 241 insertions(+), 15 deletions(-) diff --git a/.msvc/usbdos_2010.vcxproj b/.msvc/usbdos_2010.vcxproj index ba774461..a4ae8fbf 100644 --- a/.msvc/usbdos_2010.vcxproj +++ b/.msvc/usbdos_2010.vcxproj @@ -78,7 +78,7 @@ Level3 - comctl32.lib;%(AdditionalDependencies) + setupapi.lib;comctl32.lib;%(AdditionalDependencies) HighestAvailable true Windows @@ -98,7 +98,7 @@ ProgramDatabase - comctl32.lib;%(AdditionalDependencies) + setupapi.lib;comctl32.lib;%(AdditionalDependencies) HighestAvailable true Windows @@ -113,7 +113,7 @@ Level3 - comctl32.lib;%(AdditionalDependencies) + setupapi.lib;comctl32.lib;%(AdditionalDependencies) HighestAvailable false Windows @@ -131,7 +131,7 @@ Level3 - comctl32.lib;%(AdditionalDependencies) + setupapi.lib;comctl32.lib;%(AdditionalDependencies) HighestAvailable false Windows diff --git a/usbdos.c b/usbdos.c index e5bfa85d..c36f5b16 100644 --- a/usbdos.c +++ b/usbdos.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "msapi_utf8.h" #include "resource.h" @@ -30,19 +32,234 @@ /* * Globals */ -HINSTANCE main_instance; +static HINSTANCE main_instance; +static HWND hDeviceList; + +#ifdef USBDOS_DEBUG +static void _uprintf(const char *format, ...) +{ + char buf[4096], *p = buf; + va_list args; + int n; + + va_start(args, format); + n = safe_vsnprintf(p, sizeof(buf)-3, format, args); // buf-3 is room for CR/LF/NUL + va_end(args); + + p += (n < 0)?sizeof(buf)-3:n; + + while((p>buf) && (isspace(p[-1]))) + *--p = '\0'; + + *p++ = '\r'; + *p++ = '\n'; + *p = '\0'; + + OutputDebugStringA(buf); +} +#define uprintf(...) _uprintf(__VA_ARGS__) +#else +#define uprintf(...) +#endif /* - * Main dialog callback + * Converts a windows error to human readable string + * uses retval as errorcode, or, if 0, use GetLastError() */ +static char *WindowsErrorString(DWORD retval) +{ +static char err_string[256]; + + DWORD size; + DWORD error_code, format_error; + + error_code = retval?retval:GetLastError(); + + safe_sprintf(err_string, sizeof(err_string), "[%d] ", error_code); + + size = FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[strlen(err_string)], + sizeof(err_string)-(DWORD)strlen(err_string), NULL); + if (size == 0) { + format_error = GetLastError(); + if (format_error) + safe_sprintf(err_string, sizeof(err_string), + "Windows error code %u (FormatMessage error code %u)", error_code, format_error); + else + safe_sprintf(err_string, sizeof(err_string), "Unknown error code %u", error_code); + } + return err_string; +} + +/* + * Returns the drive letter (0 if error) and fills the drive label + */ +char GetDriveInfo(DWORD num, char** label) +{ + BOOL r, ret = FALSE; + DWORD size; + HANDLE hDrive; + STORAGE_DEVICE_NUMBER sdn = {0}; + static char volume_label[MAX_PATH]; + static char drives[26*2]; + char *drive = drives; + char drive_name[] = "\\\\.\\#:"; + + *label = "NO_LABEL"; + + size = GetLogicalDriveStringsA(sizeof(drives), drives); + if (size == 0) { + uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString(0)); + return 0; + } + if (size > sizeof(drives)) { + uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives)); + return FALSE; + } + + for ( ;*drive; drive += safe_strlen(drive)+1) { + if (*drive < 'C') { + continue; + } + safe_sprintf(drive_name, sizeof(drive_name), "\\\\.\\%c:", drive[0]); + hDrive = CreateFileA(drive_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + if (hDrive == INVALID_HANDLE_VALUE) { + uprintf("Could not open drive %c: %s\n", WindowsErrorString(0)); + continue; + } + + r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, + 0, &sdn, sizeof(sdn), &size, NULL); + if ((!r) || (size <= 0)) { + uprintf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed: %s\n", WindowsErrorString(0)); + CloseHandle(hDrive); + return 0; + } + if (sdn.DeviceNumber == num) + break; + CloseHandle(hDrive); + } + + if (*drive && GetVolumeInformationA(drive, volume_label, sizeof(volume_label), NULL, NULL, NULL, NULL, 0)) { + *label = volume_label; + } + + return *drive; +} + +/* + * Refreshes the list of USB devices + */ +static BOOL GetUSBDevices(void) +{ + BOOL r; + HDEVINFO dev_info = NULL; + SP_DEVINFO_DATA dev_info_data; + SP_DEVICE_INTERFACE_DATA devint_data; + PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data; + STORAGE_DEVICE_NUMBER storage_device; + DWORD size, i, j, datatype; + HANDLE hDrive; + char drive_letter; + char *label, entry[MAX_PATH], buffer[MAX_PATH]; + + IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList)); + + dev_info = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); + if (dev_info == INVALID_HANDLE_VALUE) { + uprintf("SetupDiGetClassDevs (Interface) failed: %d\n", WindowsErrorString(0)); + return FALSE; + } + + dev_info_data.cbSize = sizeof(dev_info_data); + for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { + memset(buffer, 0, sizeof(buffer)); + if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME, + &datatype, (LPBYTE)buffer, sizeof(buffer), &size)) { + uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %d\n", WindowsErrorString(0)); + continue; + } + + if (safe_strcmp(buffer, "USBSTOR") != 0) + continue; + memset(buffer, 0, sizeof(buffer)); + if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_FRIENDLYNAME, + &datatype, (LPBYTE)buffer, sizeof(buffer), &size)) { + uprintf("SetupDiGetDeviceRegistryProperty (Friendly Name) failed: %d\n", WindowsErrorString(0)); + continue; + } + uprintf("found drive '%s'\n", buffer); + + devint_data.cbSize = sizeof(devint_data); + devint_detail_data = NULL; + for (j=0;;j++) { + if (!SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &GUID_DEVINTERFACE_DISK, j, &devint_data)) { + if(GetLastError() != ERROR_NO_MORE_ITEMS) { + uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString(0)); + } + break; + } + + if (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) { + if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size); + if (devint_detail_data == NULL) { + uprintf("unable to allocate data for SP_DEVICE_INTERFACE_DETAIL_DATA\n"); + return FALSE; + } + devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + } else { + uprintf("SetupDiGetDeviceInterfaceDetail (dummy) failed: %s\n", WindowsErrorString(0)); + continue; + } + } + if(!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) { + uprintf("SetupDiGetDeviceInterfaceDetail (actual) failed: %s\n", WindowsErrorString(0)); + continue; + } + + hDrive = CreateFileA(devint_detail_data->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if(hDrive == INVALID_HANDLE_VALUE) { + uprintf("could not open '%s': %s\n", devint_detail_data->DevicePath, WindowsErrorString(0)); + continue; + } + safe_free(devint_detail_data); + + memset(&storage_device, 0, sizeof(storage_device)); + r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, + NULL, 0, &storage_device, sizeof(storage_device), &size, NULL ); + if (!r || size <= 0) { + uprintf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed: %s\n", WindowsErrorString(0)); + CloseHandle(hDrive); + continue; + } + CloseHandle(hDrive); + + drive_letter = GetDriveInfo(storage_device.DeviceNumber, &label); + if (drive_letter) { + safe_sprintf(entry, sizeof(entry), "%s (%c:)\n", label, drive_letter); + IGNORE_RETVAL(ComboBox_AddStringU(hDeviceList, entry)); + } + } + } + IGNORE_RETVAL(ComboBox_SetCurSel(hDeviceList, 0)); + return TRUE; +} + +/* +* Main dialog callback +*/ static INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DEVICECHANGE: + GetUSBDevices(); return (INT_PTR)TRUE; case WM_INITDIALOG: + hDeviceList = GetDlgItem(hDlg, IDC_DEVICE); + GetUSBDevices(); return (INT_PTR)TRUE; case WM_COMMAND: @@ -111,6 +328,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine HWND hDlg = NULL; MSG msg; + uprintf("*** USBDOS INIT ***\n"); + // Prevent 2 applications from running at the same time mutex = CreateMutexA(NULL, TRUE, "Global/USBDOS"); if ((mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) @@ -144,6 +363,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine out: CloseHandle(mutex); + uprintf("*** USBDOS EXIT ***\n"); return 0; } diff --git a/usbdos.h b/usbdos.h index b54690b1..a98e47fe 100644 --- a/usbdos.h +++ b/usbdos.h @@ -18,17 +18,10 @@ #pragma once -#if !defined(bool) -#define bool BOOL -#endif -#if !defined(true) -#define true TRUE -#endif -#if !defined(false) -#define false FALSE -#endif +#define USBDOS_DEBUG #define APP_VERSION "USBDOS v0.1.0.1" +#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0) #define safe_free(p) do {free((void*)p); p = NULL;} while(0) #define safe_min(a, b) min((size_t)(a), (size_t)(b)) @@ -44,3 +37,16 @@ #define safe_sprintf _snprintf #define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str)) #define safe_strdup _strdup + +#if defined(_MSC_VER) +#define safe_vsnprintf(buf, size, format, arg) _vsnprintf_s(buf, size, _TRUNCATE, format, arg) +#else +#define safe_vsnprintf vsnprintf +#endif + +typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS { + SCSI_PASS_THROUGH Spt; + ULONG Filler; + UCHAR SenseBuf[32]; + UCHAR DataBuf[512]; +} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;