Я написал код для поиска установленных модемов на компьютере. Это может найти имя устройства, которое полезно для отображения, но пока не может найти COM-порт модема. Мне нужно это, чтобы использовать устройство. Как я могу получить эту информацию, учитывая то, что я могу обнаружить с помощью API установки Microsoft Device and Drive?
Вот код:
/*
use CM_Get_Device_Interface_ListW and CM_Get_Device_Interface_List_SizeW for get
list of interfaces for GUID_DEVINTERFACE_COMPORT. query CM_Get_Device_Interface_PropertyW
with DEVPKEY_Device_InstanceId for get device id, than CM_Locate_DevNodeW and finally
you can query devnode for many properties - like DEVPKEY_NAME, etc.
*/
#include <Windows.h>
#include <cfgmgr32.h> // Device and Driver Installation header
#include <initguid.h> // Put this in to get rid of linker errors - unresolved external symbol _DEVPKEY_Device_DeviceDesc
#include <devpkey.h> // Property keys defined here are now defined inline. DEVPKEY_Device_DeviceDesc
// Microsoft Device and Driver Installation library
#pragma comment(lib, "Cfgmgr32.lib")
#include <Ntddmodm.h>
#include <iostream>
#include <string>
using namespace std;
const char* error2string(int err) {
switch (err) {
case CR_SUCCESS: return "CR_OK";
case CR_DEFAULT: return "CR_DEFAULT";
case CR_OUT_OF_MEMORY: return "CR_OUT_OF_MEMORY";
case CR_INVALID_POINTER: return "CR_INVALID_POINTER";
case CR_INVALID_FLAG: return "CR_INVALID_FLAG";
case CR_INVALID_DEVNODE: return "CR_INVALID_DEVNODE";
case CR_INVALID_RES_DES: return "CR_INVALID_RES_DES";
case CR_INVALID_LOG_CONF: return "CR_INVALID_LOG_CONF";
case CR_INVALID_ARBITRATOR: return "CR_INVALID_ARBITRATOR";
case CR_INVALID_NODELIST: return "CR_INVALID_NODELIST";
case CR_DEVNODE_HAS_REQS: return "CR_DEVNODE_HAS_REQS";
case CR_INVALID_RESOURCEID: return "CR_INVALID_RESOURCEID";
case CR_DLVXD_NOT_FOUND: return "CR_DLVXD_NOT_FOUND";
case CR_NO_SUCH_DEVNODE: return "CR_NO_SUCH_DEVNODE";
case CR_NO_MORE_LOG_CONF: return "CR_NO_MORE_LOG_CONF";
case CR_NO_MORE_RES_DES: return "CR_NO_MORE_RES_DES";
case CR_ALREADY_SUCH_DEVNODE: return "CR_ALREADY_SUCH_DEVNODE";
case CR_INVALID_RANGE_LIST: return "CR_INVALID_RANGE_LIST";
case CR_INVALID_RANGE: return "CR_INVALID_RANGE";
case CR_FAILURE: return "CR_FAILURE";
case CR_NO_SUCH_LOGICAL_DEV: return "CR_NO_SUCH_LOGICAL_DEV";
case CR_CREATE_BLOCKED: return "CR_CREATE_BLOCKED";
case CR_NOT_SYSTEM_VM: return "CR_NOT_SYSTEM_VM";
case CR_REMOVE_VETOED: return "CR_REMOVE_VETOED";
case CR_APM_VETOED: return "CR_APM_VETOED";
case CR_INVALID_LOAD_TYPE: return "CR_INVALID_LOAD_TYPE";
case CR_BUFFER_SMALL: return "CR_BUFFER_SMALL";
case CR_NO_ARBITRATOR: return "CR_NO_ARBITRATOR";
case CR_NO_REGISTRY_HANDLE: return "CR_NO_REGISTRY_HANDLE";
case CR_REGISTRY_ERROR: return "CR_REGISTRY_ERROR";
case CR_INVALID_DEVICE_ID: return "CR_INVALID_DEVICE_ID";
case CR_INVALID_DATA: return "CR_INVALID_DATA";
case CR_INVALID_API: return "CR_INVALID_API";
case CR_DEVLOADER_NOT_READY: return "CR_DEVLOADER_NOT_READY";
case CR_NEED_RESTART: return "CR_NEED_RESTART";
case CR_NO_MORE_HW_PROFILES: return "CR_NO_MORE_HW_PROFILES";
case CR_DEVICE_NOT_THERE: return "CR_DEVICE_NOT_THERE";
case CR_NO_SUCH_VALUE: return "CR_NO_SUCH_VALUE";
case CR_WRONG_TYPE: return "CR_WRONG_TYPE";
case CR_INVALID_PRIORITY: return "CR_INVALID_PRIORITY";
case CR_NOT_DISABLEABLE: return "CR_NOT_DISABLEABLE";
case CR_FREE_RESOURCES: return "CR_FREE_RESOURCES";
case CR_QUERY_VETOED: return "CR_QUERY_VETOED";
case CR_CANT_SHARE_IRQ: return "CR_CANT_SHARE_IRQ";
case CR_NO_DEPENDENT: return "CR_NO_DEPENDENT";
case CR_SAME_RESOURCES: return "CR_SAME_RESOURCES";
case CR_NO_SUCH_REGISTRY_KEY: return "CR_NO_SUCH_REGISTRY_KEY";
case CR_INVALID_MACHINENAME: return "CR_INVALID_MACHINENAME";
case CR_REMOTE_COMM_FAILURE: return "CR_REMOTE_COMM_FAILURE";
case CR_MACHINE_UNAVAILABLE: return "CR_MACHINE_UNAVAILABLE";
case CR_NO_CM_SERVICES: return "CR_NO_CM_SERVICES";
case CR_ACCESS_DENIED: return "CR_ACCESS_DENIED";
case CR_CALL_NOT_IMPLEMENTED: return "CR_CALL_NOT_IMPLEMENTED";
case CR_INVALID_PROPERTY: return "CR_INVALID_PROPERTY";
case CR_DEVICE_INTERFACE_ACTIVE: return "CR_DEVICE_INTERFACE_ACTIVE";
case CR_NO_SUCH_DEVICE_INTERFACE: return "CR_NO_SUCH_DEVICE_INTERFACE";
case CR_INVALID_REFERENCE_STRING: return "CR_INVALID_REFERENCE_STRING";
case CR_INVALID_CONFLICT_LIST: return "CR_INVALID_CONFLICT_LIST";
case CR_INVALID_INDEX: return "CR_INVALID_INDEX";
case CR_INVALID_STRUCTURE_SIZE: return "CR_INVALID_STRUCTURE_SIZE";
case NUM_CR_RESULTS: return "NUM_CR_RESULTS";
default: return "unknown";
}
}
void printerror(int line, int code) {
cout << "error: " << error2string(code) << " on line " << line << endl;
}
void print_filtered_devices() {
/* find properties for GUID_DEVINTERFACE_COMPORT and GUID_DEVINTERFACE_MODEM */
LPGUID InterfaceClassGuid = (LPGUID)&GUID_DEVINTERFACE_MODEM;
PWSTR DeviceList = NULL;
ULONG DeviceListLength = 0;
CONFIGRET cr = CM_Get_Device_Interface_List_SizeW(&DeviceListLength, InterfaceClassGuid, 0, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr == CR_SUCCESS) {
DeviceList = (PWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DeviceListLength * sizeof(WCHAR));
cr = CM_Get_Device_Interface_ListW(InterfaceClassGuid, NULL, DeviceList, DeviceListLength, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr == CR_SUCCESS) {
for (PWSTR CurrentDevice = DeviceList; *CurrentDevice; CurrentDevice += wcslen(CurrentDevice) + 1) {
wcout << L"interface = " << CurrentDevice << endl;
DEVPROPTYPE PropertyType;
WCHAR buf[1024];
ULONG BufferSize = sizeof(buf);
cr = CM_Get_Device_Interface_PropertyW(CurrentDevice, &DEVPKEY_Device_InstanceId, &PropertyType, (PBYTE)buf, &BufferSize, 0);
cout << "CM_Get_Device_Interface_PropertyW returned: " << error2string(cr) << endl;
DEVINST Devinst;
cr = CM_Locate_DevNodeW(&Devinst, buf, CM_LOCATE_DEVNODE_NORMAL);
cout << "CM_Locate_DevNodeW returned: " << error2string(cr) << endl;
if (cr == CR_SUCCESS) {
// Query a property on the device. For example, the device description.
WCHAR DeviceDesc[2048];
ULONG PropertySize = sizeof(DeviceDesc);
cr = CM_Get_DevNode_PropertyW(Devinst,
&DEVPKEY_Device_DeviceDesc,
&PropertyType,
(PBYTE)DeviceDesc,
&PropertySize,
0);
cout << "CM_Get_DevNode_PropertyW returned: " << error2string(cr) << endl;
if (cr == CR_SUCCESS && PropertyType == DEVPROP_TYPE_STRING) {
// print device
wcout << "DEVPKEY_Device_DeviceDesc=" << DeviceDesc << endl;
wcout << "";
}
else {
printerror(__LINE__, cr);
}
//WCHAR DeviceDesc[2048];
PropertySize = sizeof(DeviceDesc);
cr = CM_Get_DevNode_PropertyW(Devinst,
&DEVPKEY_NAME,
&PropertyType,
(PBYTE)DeviceDesc,
&PropertySize,
0);
cout << "CM_Get_DevNode_PropertyW returned: " << error2string(cr) << endl;
if (cr == CR_SUCCESS && PropertyType == DEVPROP_TYPE_STRING) {
// print device
wcout << "DEVPKEY_NAME=" << DeviceDesc << endl;
wcout << "";
}
else {
printerror(__LINE__, cr);
}
//Need a port property???
}
else {
printerror(__LINE__, cr);
}
}
}
else {
printerror(__LINE__, cr);
}
}
else {
printerror(__LINE__, cr);
}
if (DeviceList != NULL) {
HeapFree(GetProcessHeap(), 0, DeviceList);
}
}
int main() {
// This call fails to retrieve any devices of class GUID_DEVINTERFACE_COMPORT
print_filtered_devices();
}
И на моем компьютере я получаю этот вывод:
interface = \\?\USB#VID_0572&PID_1340#12345678#{2c7089aa-2e0e-11d1-b114-00c04fc2aae4}
CM_Get_Device_Interface_PropertyW returned: CR_OK
CM_Locate_DevNodeW returned: CR_OK
CM_Get_DevNode_PropertyW returned: CR_OK
DEVPKEY_Device_DeviceDesc=Conexant USB CX93010 ACF Modem
CM_Get_DevNode_PropertyW returned: CR_OK
DEVPKEY_NAME=Conexant USB CX93010 ACF Modem