Ok, I found a piece of code inside of one of my projects (I wrote it some 2 years ago, and worked at that time).
class devenum {
private:
devenum();
~devenum();
devenum(const devenum&);
devenum& operator=(const devenum&);
public:
static bool get(vector_t< pair_t< string_t<wchar_t>, string_t<wchar_t> > > & info) {
HDEVINFO hdevinfo = ::SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if(hdevinfo == INVALID_HANDLE_VALUE) {
return false;
}
SP_DEVINFO_DATA did = {0};
did.cbSize = sizeof(did);
for(DWORD i = 0; ::SetupDiEnumDeviceInfo(hdevinfo, i, &did); i++) {
string_t<wchar_t> desc;
if(getDescription(hdevinfo, &did, desc)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L"description", desc);
}
string_t<wchar_t> hwid;
if(getHardwareID(hdevinfo, &did, hwid)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" hardware-id", hwid);
}
string_t<wchar_t> clas;
if(getClass(hdevinfo, &did, clas)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" class", clas);
}
string_t<wchar_t> classGuid;
if(getClassGuid(hdevinfo, &did, classGuid)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" class-guid", classGuid);
}
string_t<wchar_t> address;
if(getAddress(hdevinfo, &did, address)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" address", address);
}
string_t<wchar_t> busnumber;
if(getBusNumber(hdevinfo, &did, busnumber)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" bus-number", busnumber);
}
string_t<wchar_t> bustypeguid;
if(getBusTypeGuid(hdevinfo, &did, bustypeguid)) {
info += pair_t< string_t<wchar_t>, string_t<wchar_t> >(L" bus-type-guid", bustypeguid);
}
}
::SetupDiDestroyDeviceInfoList(hdevinfo);
return true;
}
static bool getDescription(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getString(hdevinfo, pdid, SPDRP_DEVICEDESC, str);
}
static bool getHardwareID(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getString(hdevinfo, pdid, SPDRP_HARDWAREID, str);
}
static bool getClass(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getString(hdevinfo, pdid, SPDRP_CLASS, str);
}
static bool getClassGuid(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getString(hdevinfo, pdid, SPDRP_CLASSGUID, str);
}
static bool getAddress(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getDWORD(hdevinfo, pdid, SPDRP_ADDRESS, str);
}
static bool getBusNumber(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getDWORD(hdevinfo, pdid, SPDRP_BUSNUMBER, str);
}
static bool getBusTypeGuid(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, string_t<wchar_t>& str) {
return getByte(hdevinfo, pdid, SPDRP_BUSTYPEGUID, str);
}
static bool getString(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, DWORD propid, string_t<wchar_t>& str) {
DWORD type = 0;
DWORD bufsiz = 0;
LPWSTR pw = NULL;
bool ok = true;
do {
if(::SetupDiGetDeviceRegistryPropertyW(hdevinfo, pdid, propid,
&type, (PBYTE)pw, bufsiz, &bufsiz)) {
ok = true;
break;
}
if(::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
ok = true;
if(pw != NULL) {
::LocalFree(pw);
}
pw = (LPWSTR)LocalAlloc(LPTR, bufsiz * 2 + 1);
if(pw == NULL) {
break;
}
}
else {
ok = false;
break;
}
#pragma warning(disable: 4127)
} while(true);
#pragma warning(default: 4127)
if(ok) {
if(pw != NULL) {
str = pw;
}
}
else {
ok = true;
str = L"";
}
if(pw != NULL) {
::LocalFree(pw);
}
return ok;
}
static bool getDWORD(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, DWORD propid, string_t<wchar_t>& str) {
DWORD type = 0;
DWORD bufsiz = 0;
DWORD v = 0;
if(!::SetupDiGetDeviceRegistryPropertyW(hdevinfo, pdid, propid,
&type, (PBYTE)&v, sizeof(DWORD), &bufsiz)) {
str = L"";
return true;
}
WCHAR sz[40] = L"";
swprintf_s(sz, _countof(sz), L"0x%8.8x", v);
str = sz;
return true;
}
static bool getByte(HDEVINFO hdevinfo, SP_DEVINFO_DATA* pdid, DWORD propid, string_t<wchar_t>& str) {
DWORD type = 0;
DWORD bufsiz = 0;
LPBYTE pb = NULL;
bool ok = true;
do {
if(::SetupDiGetDeviceRegistryPropertyW(hdevinfo, pdid, propid,
&type, (PBYTE)pb, bufsiz, &bufsiz)) {
ok = true;
break;
}
if(::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
ok = true;
if(pb != NULL) {
::LocalFree(pb);
}
pb = (LPBYTE)LocalAlloc(LPTR, bufsiz * 2);
if(pb == NULL) {
break;
}
}
else {
ok = false;
break;
}
#pragma warning(disable: 4127)
} while(true);
#pragma warning(default: 4127)
if(ok) {
if(bufsiz == sizeof(GUID)) {
GUID* guid = (GUID *)pb;
WCHAR sz[40] = L"";
memset(&sz[0], 0, _countof(sz) * sizeof(WCHAR));
int rez = ::StringFromGUID2(*guid, sz, _countof(sz) - 1);
if(rez != 0) {
str = sz;
ok = true;
}
}
}
else {
ok = true;
str = L"";
}
if(pb != NULL) {
::LocalFree(pb);
}
return ok;
}
};
The string_t is a string class, but you can replace it with std::wstring (or a LPWSTR* output variable as well). Same for vector_t, pair_t - you can replace them with STL counterparts std::vector, std::pair with minimal or no changes.
The getDescription is what you are looking for, which in turn calls getString - this is the core of business.
The usage - in my project - is:
vector_t< pair_t< string_t<wchar_t>, string_t<wchar_t> > > info;
devenum::get(info);
I can post somewhere the entire project but the message form does not support attachments. Maybe I will post the entire project here as an article soon.
Regards,
Cristian
Nuclear launch detected
|