mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[enum] populate the device list
This commit is contained in:
parent
7b84a6adff
commit
e041eea1df
3 changed files with 241 additions and 15 deletions
|
@ -78,7 +78,7 @@
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>setupapi.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>setupapi.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
@ -113,7 +113,7 @@
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>setupapi.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
||||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>setupapi.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
<UACExecutionLevel>HighestAvailable</UACExecutionLevel>
|
||||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
|
224
usbdos.c
224
usbdos.c
|
@ -22,6 +22,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
#include <setupapi.h>
|
||||||
|
#include <ntddscsi.h>
|
||||||
|
|
||||||
#include "msapi_utf8.h"
|
#include "msapi_utf8.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
@ -30,19 +32,234 @@
|
||||||
/*
|
/*
|
||||||
* Globals
|
* 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)
|
static INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
switch (message) {
|
switch (message) {
|
||||||
|
|
||||||
case WM_DEVICECHANGE:
|
case WM_DEVICECHANGE:
|
||||||
|
GetUSBDevices();
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
|
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
|
hDeviceList = GetDlgItem(hDlg, IDC_DEVICE);
|
||||||
|
GetUSBDevices();
|
||||||
return (INT_PTR)TRUE;
|
return (INT_PTR)TRUE;
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
|
@ -111,6 +328,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
HWND hDlg = NULL;
|
HWND hDlg = NULL;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
|
uprintf("*** USBDOS INIT ***\n");
|
||||||
|
|
||||||
// Prevent 2 applications from running at the same time
|
// Prevent 2 applications from running at the same time
|
||||||
mutex = CreateMutexA(NULL, TRUE, "Global/USBDOS");
|
mutex = CreateMutexA(NULL, TRUE, "Global/USBDOS");
|
||||||
if ((mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
|
if ((mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
|
||||||
|
@ -144,6 +363,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
|
|
||||||
out:
|
out:
|
||||||
CloseHandle(mutex);
|
CloseHandle(mutex);
|
||||||
|
uprintf("*** USBDOS EXIT ***\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
24
usbdos.h
24
usbdos.h
|
@ -18,17 +18,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if !defined(bool)
|
#define USBDOS_DEBUG
|
||||||
#define bool BOOL
|
|
||||||
#endif
|
|
||||||
#if !defined(true)
|
|
||||||
#define true TRUE
|
|
||||||
#endif
|
|
||||||
#if !defined(false)
|
|
||||||
#define false FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define APP_VERSION "USBDOS v0.1.0.1"
|
#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_free(p) do {free((void*)p); p = NULL;} while(0)
|
||||||
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
|
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
|
||||||
|
@ -44,3 +37,16 @@
|
||||||
#define safe_sprintf _snprintf
|
#define safe_sprintf _snprintf
|
||||||
#define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str))
|
#define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str))
|
||||||
#define safe_strdup _strdup
|
#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;
|
||||||
|
|
Loading…
Reference in a new issue