demo code:
struct DeviceName : public LIST_ENTRY
{
ULONG InterfaceHash;
WCHAR Name[];
void* operator new(size_t cb, size_t len)
{
return LocalAlloc(0, cb + len);
}
void operator delete(void* pv)
{
LocalFree(pv);
}
};
volatile const UCHAR guz = 0;
CONFIGRET GetFriendlyNameByDevNode(DeviceName** pp, DEVINST dnDevInst)
{
CONFIGRET status;
ULONG cb = 32;
DEVPROPTYPE PropertyType;
do
{
if (DeviceName* p = new(cb) DeviceName)
{
status = CM_Get_DevNode_PropertyW(
dnDevInst, &DEVPKEY_DeviceInterface_FriendlyName, &PropertyType, (PBYTE)p->Name, &cb, 0);
if (status == CR_SUCCESS)
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
*pp = p;
return CR_SUCCESS;
}
else
{
status = CR_WRONG_TYPE;
}
}
delete p;
}
else
{
status = CR_OUT_OF_MEMORY;
}
} while (CR_BUFFER_SMALL == status);
return status;
}
CONFIGRET GetFriendlyNameByInterface(DeviceName** pp, PCWSTR pszDeviceInterface)
{
// RTCu must be disabled !
ULONG cb = 0, rcb = 64;
PVOID stack = alloca(guz);
DEVPROPTYPE PropertyType;
CONFIGRET status;
union {
PVOID pv;
PWSTR DeviceID;
PBYTE pb;
};
do
{
if (cb < rcb)
{
rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
}
} while (CR_BUFFER_SMALL == (status = CM_Get_Device_Interface_PropertyW(
pszDeviceInterface, &DEVPKEY_Device_InstanceId, &PropertyType, pb, &rcb, 0)));
if (status == CR_SUCCESS)
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DEVINST dnDevInst;
status = CM_Locate_DevNodeW(&dnDevInst, DeviceID, CM_LOCATE_DEVNODE_NORMAL);
return status == CR_SUCCESS ? GetFriendlyNameByDevNode(pp, dnDevInst) : status;
}
else
{
status = CR_WRONG_TYPE;
}
}
return status;
}
case WM_DESTROY:
if (_hDevNot)
{
UnregisterDeviceNotification(_hDevNot);
PLIST_ENTRY head = &_DevListHead, entry = head->Flink;
while (entry != head)
{
DeviceName* p = static_cast<DeviceName*>(entry);
entry = entry->Flink;
delete p;
}
}
break;
case WM_DEVICECHANGE:
switch (wParam)
{
case DBT_DEVICEREMOVECOMPLETE:
case DBT_DEVICEARRIVAL:
if (reinterpret_cast<PDEV_BROADCAST_DEVICEINTERFACE>(lParam)->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
DeviceName* p;
ULONG InterfaceHash;
UNICODE_STRING dbcc_name;
RtlInitUnicodeString(&dbcc_name, reinterpret_cast<PDEV_BROADCAST_DEVICEINTERFACE>(lParam)->dbcc_name);
RtlHashUnicodeString(&dbcc_name, FALSE, HASH_STRING_ALGORITHM_DEFAULT, &InterfaceHash);
if (wParam == DBT_DEVICEARRIVAL)
{
if (CR_SUCCESS == GetFriendlyNameByInterface(&p, dbcc_name.Buffer))
{
p->InterfaceHash = InterfaceHash;
InsertHeadList(&_DevListHead, p);
DbgPrint("inserted %S ( %wZ )\n", p->Name, &dbcc_name);
}
}
else
{
PLIST_ENTRY head = &_DevListHead, entry = head;
while ((entry = entry->Flink) != head)
{
if (static_cast<DeviceName*>(entry)->InterfaceHash == InterfaceHash)
{
DbgPrint("removed %S ( %wZ )\n",
static_cast<DeviceName*>(entry)->Name, &dbcc_name);
RemoveEntryList(entry);
delete static_cast<DeviceName*>(entry);
break;
}
}
}
}
break;
}
return 0;
case WM_CREATE:
InitializeListHead(&_DevListHead);
static DEV_BROADCAST_DEVICEINTERFACE dbd = { sizeof(dbd), DBT_DEVTYP_DEVICEINTERFACE };
_hDevNot = RegisterDeviceNotificationW(hwnd, &dbd, DEVICE_NOTIFY_WINDOW_HANDLE|DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
break;