Функции, которые осуществляют работу с устройствами, находятся в системных библиотеках cfgmgr32.dll и setupapi.dll. Для работы с системными библиотеками в C++ Builder 6 используется заголовочный файл setupapi.h.
Устройства в системе подразделяются на классы, например: класс видеоустройств, принтеров, модемы, клавиатуры и т.д. Любое устройство должно принадлежать как-нибудь классу. Каждый класс идентифицируется своим GUID’ом (глобальный уникальный идентификатор). GUID это 128 битная запись типа: {C06136A2-43EA-4F43-AF06-7413D07E28B7}.
Список GUID’ов для некоторых устройств:
Тип устройства | Идентификатор |
Монитор | {4D36E96E-E325-11CE-BFC1-08002BE10318} |
PCI | {4D36E968-E325-11CE-BFC1-08002BE10318} |
USB устройства | {36FC9E60-C465-11CF-8056-444553540000} |
Дисковые накопители информации | {4D36E967-E325-11CE-BFC1-08002BE10318} |
Описание структуры GUID:
typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;
Для записи данных в структуру GUID в C++ Builder используются следующая запись:
GUID GUID_USB_DEVICE={ 0xC06136A2, 0x43EA, 0x4F43, 0xAF, 0x06, 0x74, 0x13, 0xD0, 0x7E, 0x28, 0xB7};
Получение списка устройств принадлежащих заданному GUID’у осуществляет функция SetupDiGetClassDevs:
|
|
HDEVINFO
SetupDiGetClassDevs(
IN LPGUID ClassGuid, OPTIONAL
IN PCTSTR Enumerator, OPTIONAL
IN HWND hwndParent, OPTIONAL
IN DWORD Flags
);
У этой функции почти все параметры опциональны за исключением последнего. Первый параметр задаёт класс устройств для перечисления. Если этот параметр равен нулю, то перечисляться будут все устройства в системе. Второй и третий параметры (соответственно, имя PnP перечислителя и HANDLE формы) могут быть равны нулю. Последний параметр самый важный. Он может принимать одно из следующий значений или их комбинацию:
DIGCF_ALLCLASSES – будет возвращён список всех устройств и всех классов, установленных в данный момент в системе. Первый параметр будет проигнорирован.
DIGCF_DEVICEINTERFACE – возврат списка устройств, которые поддерживают интерфейсы.
DIGCF_DEFAULT – возврат списка устройств, которые ассоциируются с системой по умолчанию.
DIGCF_PRESENT – будет возвращён список устройств, которые в настоящее время присутствуют в системе.
DIGCF_PROFILE – будет возвращён список устройств, которые являются частью текущего аппаратного профиля.
При успешном вызове функция возвращает хендл полученного списка.
Для перечисления всех устройств по заданному хендлу используется функция SetupDiEnumDeviceInfo:
WINSETUPAPI BOOL WINAPI
SetupDiEnumDeviceInfo(
IN HDEVINFO DeviceInfoSet,
IN DWORD MemberIndex,
OUT PSP_DEVINFO_DATA DeviceInfoData
);
Первый параметр указатель списка устройств. Второй парметр задаёт индекс в списке. Третий параметр это указатель на структуру SP_DEVINFO_DATA, в которой будет сохранена информация об устройстве. Если функция вернула значение TRUE, то информация извлечена успешно, а если FALSE, то в большинстве случаев это означает что мы пришли к концу списка. Для перечисления всего списка нужно в цикле вызывать функцию SetupDiEnumDeviceInfo каждый раз увеличивая значение индекса на единицу до тех пор пока не получим отрицательный результат.
|
|
Структура, в которой хранится информация об устройстве:
typedef struct _SP_DEVINFO_DATA {
DWORD cbSize;
GUID ClassGuid;
DWORD DevInst;
ULONG_PTR Reserved;
};
Для того чтобы получить имя устройства (или его описание) нужно использовать функцию SetupDiGetDeviceRegistryProperty:
WINSETUPAPI BOOL WINAPI
SetupDiGetDeviceRegistryProperty(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN DWORD Property,
OUT PDWORD PropertyRegDataType, OPTIONAL
OUT PBYTE PropertyBuffer,
IN DWORD PropertyBufferSize,
OUT PDWORD RequiredSize OPTIONAL
);
Второй параметр это указатель на структуру SP_DEVINFO_DATA. Третий параметр задаёт тип информации, которую нужно получить:
SPDRP_ADDRESS – функция получает адрес устройства;
SPDRP_BUSNUMBER – функция получает номер драйвера устройства;
SPDRP_BUSTYPEGUID – функция получает GUID для драйвера устройства;
SPDRP_CLASS – функция получает строку, которая содержит класс устройства;
SPDRP_DEVICEDESC – функция получает описание устройства;
SPDRP_DEVTYPE – функция получает тип устройства.
Если функция вернёт False, а функция GetLastError() будет равна ERROR_INSUFFICIENT_BUFFER, то необходимо увеличить размер буфера и вызывать функцию заново.
Для увеличения размера буфера можно использовать следующий алгоритм:
LocalFree(buffer);
buffer = (char*)LocalAlloc(LPTR,buffersize*2);