mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add method to winutil to query system for PNP device ids without using WMI
This commit is contained in:
parent
bd536ed790
commit
8a5d3cfaba
@ -208,10 +208,10 @@ static BOOL
|
||||
check_device_id(LPTSTR buffer, unsigned int vid, unsigned int pid) {
|
||||
WCHAR xVid[9], dVid[9], xPid[9], dPid[9];
|
||||
unsigned int j;
|
||||
swprintf(xVid, L"vid_%4.4x", vid);
|
||||
swprintf(dVid, L"vid_%4.4d", vid);
|
||||
swprintf(xPid, L"pid_%4.4x", pid);
|
||||
swprintf(dPid, L"pid_%4.4d", pid);
|
||||
_snwprintf_s(xVid, 9, _TRUNCATE, L"vid_%4.4x", vid);
|
||||
_snwprintf_s(dVid, 9, _TRUNCATE, L"vid_%4.4d", vid);
|
||||
_snwprintf_s(xPid, 9, _TRUNCATE, L"pid_%4.4x", pid);
|
||||
_snwprintf_s(dPid, 9, _TRUNCATE, L"pid_%4.4d", pid);
|
||||
|
||||
for (j = 0; j < wcslen(buffer); j++) buffer[j] = tolower(buffer[j]);
|
||||
|
||||
@ -220,7 +220,6 @@ check_device_id(LPTSTR buffer, unsigned int vid, unsigned int pid) {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static HDEVINFO
|
||||
create_device_info_set(LPGUID guid, PCTSTR enumerator, HWND parent, DWORD flags) {
|
||||
HDEVINFO hDevInfo;
|
||||
@ -286,7 +285,7 @@ get_all_removable_disks(struct tagDrives *g_drives)
|
||||
if(GetVolumeNameForVolumeMountPoint(caDrive, volume, BUFSIZE))
|
||||
{
|
||||
g_drives[g_count].letter = caDrive[0];
|
||||
wcscpy(g_drives[g_count].volume, volume);
|
||||
wcscpy_s(g_drives[g_count].volume, BUFSIZE, volume);
|
||||
g_count ++;
|
||||
}
|
||||
|
||||
@ -515,15 +514,17 @@ winutil_eject_drive(PyObject *self, PyObject *args) {
|
||||
|
||||
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA
|
||||
get_device_grandparent(HDEVINFO hDevInfo, DWORD index, PWSTR buf, PWSTR volume_id,
|
||||
BOOL *iterate) {
|
||||
get_device_ancestors(HDEVINFO hDevInfo, DWORD index, PyObject *candidates, BOOL *iterate, BOOL ddebug) {
|
||||
SP_DEVICE_INTERFACE_DATA interfaceData;
|
||||
SP_DEVINFO_DATA devInfoData;
|
||||
BOOL status;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
|
||||
DWORD interfaceDetailDataSize,
|
||||
reqSize;
|
||||
DEVINST parent;
|
||||
DEVINST parent, pos;
|
||||
wchar_t temp[BUFSIZE];
|
||||
int i;
|
||||
PyObject *devid;
|
||||
|
||||
interfaceData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);
|
||||
devInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
|
||||
@ -549,7 +550,7 @@ get_device_grandparent(HDEVINFO hDevInfo, DWORD index, PWSTR buf, PWSTR volume_i
|
||||
);
|
||||
|
||||
interfaceDetailDataSize = reqSize;
|
||||
interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)PyMem_Malloc(interfaceDetailDataSize+10);
|
||||
interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)PyMem_Malloc(interfaceDetailDataSize+50);
|
||||
if ( interfaceDetailData == NULL ) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
@ -563,39 +564,50 @@ get_device_grandparent(HDEVINFO hDevInfo, DWORD index, PWSTR buf, PWSTR volume_i
|
||||
interfaceDetailDataSize, // Interface detail data size
|
||||
&reqSize, // Buffer size required to get the detail data
|
||||
&devInfoData); // Interface device info
|
||||
if (ddebug) printf("Getting ancestors\n"); fflush(stdout);
|
||||
|
||||
if ( status == FALSE ) {PyErr_SetFromWindowsErr(0); PyMem_Free(interfaceDetailData); return NULL;}
|
||||
|
||||
// Get the device instance of parent. This points to USBSTOR.
|
||||
CM_Get_Parent(&parent, devInfoData.DevInst, 0);
|
||||
// Get the device ID of the USBSTORAGE volume
|
||||
CM_Get_Device_ID(parent, volume_id, BUFSIZE, 0);
|
||||
// Get the device instance of grand parent. This points to USB root.
|
||||
CM_Get_Parent(&parent, parent, 0);
|
||||
// Get the device ID of the USB root.
|
||||
CM_Get_Device_ID(parent, buf, BUFSIZE, 0);
|
||||
pos = devInfoData.DevInst;
|
||||
|
||||
for(i = 0; i < 10; i++) {
|
||||
// Get the device instance of parent.
|
||||
if (CM_Get_Parent(&parent, pos, 0) != CR_SUCCESS) break;
|
||||
if (CM_Get_Device_ID(parent, temp, BUFSIZE, 0) == CR_SUCCESS) {
|
||||
if (ddebug) wprintf(L"device id: %s\n", temp); fflush(stdout);
|
||||
devid = PyUnicode_FromWideChar(temp, wcslen(temp));
|
||||
if (devid) {
|
||||
PyList_Append(candidates, devid);
|
||||
Py_DECREF(devid);
|
||||
}
|
||||
}
|
||||
pos = parent;
|
||||
}
|
||||
|
||||
return interfaceDetailData;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
winutil_get_mounted_volumes_for_usb_device(PyObject *self, PyObject *args) {
|
||||
unsigned int vid, pid, length, j;
|
||||
winutil_get_removable_drives(PyObject *self, PyObject *args) {
|
||||
HDEVINFO hDevInfo;
|
||||
BOOL iterate = TRUE;
|
||||
BOOL iterate = TRUE, ddebug = FALSE;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
|
||||
DWORD i;
|
||||
WCHAR buf[BUFSIZE], volume[BUFSIZE], volume_id[BUFSIZE];
|
||||
unsigned int j, length;
|
||||
WCHAR volume[BUFSIZE];
|
||||
struct tagDrives g_drives[MAX_DRIVES];
|
||||
PyObject *volumes, *key, *val;
|
||||
PyObject *volumes, *key, *candidates, *pdebug = Py_False, *temp;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &vid, &pid)) {
|
||||
if (!PyArg_ParseTuple(args, "|O", &pdebug)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ddebug = PyObject_IsTrue(pdebug);
|
||||
|
||||
volumes = PyDict_New();
|
||||
if (volumes == NULL) return NULL;
|
||||
|
||||
|
||||
for (j = 0; j < MAX_DRIVES; j++) g_drives[j].letter = 0;
|
||||
|
||||
// Find all removable drives
|
||||
@ -609,47 +621,44 @@ winutil_get_mounted_volumes_for_usb_device(PyObject *self, PyObject *args) {
|
||||
|
||||
// Enumerate through the set
|
||||
for (i=0; iterate; i++) {
|
||||
interfaceDetailData = get_device_grandparent(hDevInfo, i, buf, volume_id, &iterate);
|
||||
candidates = PyList_New(0);
|
||||
if (candidates == NULL) return PyErr_NoMemory();
|
||||
|
||||
interfaceDetailData = get_device_ancestors(hDevInfo, i, candidates, &iterate, ddebug);
|
||||
if (interfaceDetailData == NULL) {
|
||||
PyErr_Print(); continue;
|
||||
}
|
||||
debug("Device num: %d Device Id: %ws\n\n", i, buf);
|
||||
if (check_device_id(buf, vid, pid)) {
|
||||
debug("Device matches\n\n");
|
||||
|
||||
length = wcslen(interfaceDetailData->DevicePath);
|
||||
interfaceDetailData->DevicePath[length] = '\\';
|
||||
interfaceDetailData->DevicePath[length] = L'\\';
|
||||
interfaceDetailData->DevicePath[length+1] = 0;
|
||||
if(GetVolumeNameForVolumeMountPoint(interfaceDetailData->DevicePath, volume, BUFSIZE)) {
|
||||
|
||||
if (ddebug) wprintf(L"Device path: %s\n", interfaceDetailData->DevicePath); fflush(stdout);
|
||||
// On Vista+ DevicePath contains the information we need.
|
||||
temp = PyUnicode_FromWideChar(interfaceDetailData->DevicePath, length);
|
||||
if (temp == NULL) return PyErr_NoMemory();
|
||||
PyList_Append(candidates, temp);
|
||||
Py_DECREF(temp);
|
||||
if(GetVolumeNameForVolumeMountPointW(interfaceDetailData->DevicePath, volume, BUFSIZE)) {
|
||||
if (ddebug) wprintf(L"Volume: %s\n", volume); fflush(stdout);
|
||||
|
||||
for(j = 0; j < MAX_DRIVES; j++) {
|
||||
// Compare volume mount point with the one stored earlier.
|
||||
// If both match, return the corresponding drive letter.
|
||||
if(g_drives[j].letter != 0 && wcscmp(g_drives[j].volume, volume)==0)
|
||||
{
|
||||
key = PyUnicode_FromWideChar(volume_id, wcslen(volume_id));
|
||||
val = PyString_FromFormat("%c", (char)g_drives[j].letter);
|
||||
if (key == NULL || val == NULL) {
|
||||
PyErr_NoMemory();
|
||||
if(g_drives[j].letter != 0 && wcscmp(g_drives[j].volume, volume)==0) {
|
||||
if (ddebug) printf("Found drive: %c\n", (char)g_drives[j].letter); fflush(stdout);
|
||||
key = PyBytes_FromFormat("%c", (char)g_drives[j].letter);
|
||||
if (key == NULL) return PyErr_NoMemory();
|
||||
PyDict_SetItem(volumes, key, candidates);
|
||||
Py_DECREF(candidates);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
PyMem_Free(interfaceDetailData);
|
||||
return NULL;
|
||||
}
|
||||
PyDict_SetItem(volumes, key, val);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
debug("Failed to get volume name for volume mount point:\n");
|
||||
if (DEBUG) debug("%ws\n\n", format_last_error());
|
||||
}
|
||||
|
||||
PyMem_Free(interfaceDetailData);
|
||||
}
|
||||
|
||||
} //for
|
||||
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
return volumes;
|
||||
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
@ -886,11 +895,12 @@ static PyMethodDef WinutilMethods[] = {
|
||||
"Return a list of the hardware IDs of all USB devices "
|
||||
"connected to the system."},
|
||||
|
||||
{"get_mounted_volumes_for_usb_device", winutil_get_mounted_volumes_for_usb_device, METH_VARARGS,
|
||||
"get_mounted_volumes_for_usb_device(vid, pid) -> dict\n\n"
|
||||
"Return a dictionary of volume_id:drive_letter for all"
|
||||
"volumes mounted on the system that belong to the"
|
||||
"usb device specified by vid (integer) and pid (integer)."},
|
||||
{"get_removable_drives", winutil_get_removable_drives, METH_VARARGS,
|
||||
"get_removable_drives(debug=False) -> dict\n\n"
|
||||
"Return mapping of all removable drives in the system. Maps drive letters "
|
||||
"to a list of device id strings, atleast one of which will carry the information "
|
||||
"needed for device matching. On Vista+ it is always the last string in the list. "
|
||||
"Note that you should upper case all strings."},
|
||||
|
||||
{"set_debug", winutil_set_debug, METH_VARARGS,
|
||||
"set_debug(bool)\n\nSet debugging mode."
|
||||
|
Loading…
x
Reference in New Issue
Block a user