What I'm basically trying to do is making a windows service that listens to storage device insertion such as (USB flash drive, external HDD/SSD)... I'm follwing these 2 tutorials :
dbch_devicetype
in PDEV_BROADCAST_HDR
is always DBT_DEVTYP_DEVICEINTERFACE
never DBT_DEVTYP_VOLUME
. Also when I RegisterDeviceNotification
with DBT_DEVTYP_VOLUME
I don't receive anything. I have been searching for hours and I could't find why I'm not receiving the correct notificationsvoid Myclassname::registerForDeviceNotifications() {
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };
m_hDevNotify = RegisterDeviceNotification(m_statusHandle,
&NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE |
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
}
The function responsible for handling the device notifications :
void AutobackupService::handleDeviceChangeNotif(DWORD dwEventType, LPVOID lpEventData) {
switch (dwEventType) {
case DBT_DEVICEREMOVECOMPLETE: {
PDEV_BROADCAST_HDR eventData = (PDEV_BROADCAST_HDR)lpEventData;
logToFile(std::to_string(eventData->dbch_devicetype));
if (eventData->dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)eventData;
if (lpdbv->dbcv_flags & DBTF_MEDIA)
{
WriteEventLogEntry(L"USB device removed " + lpdbv->dbcv_unitmask, EVENTLOG_INFORMATION_TYPE);
}
}
}
break;
case DBT_DEVICEARRIVAL: {
PDEV_BROADCAST_HDR eventData = (PDEV_BROADCAST_HDR)lpEventData;
logToFile(std::to_string(eventData->dbch_devicetype));
if (eventData->dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)eventData;
if (lpdbv->dbcv_flags & DBTF_MEDIA)
{
WriteEventLogEntry(L"USB device removed " + lpdbv->dbcv_unitmask, EVENTLOG_INFORMATION_TYPE);
}
}
}
}
}
at first your wrong register for volume notification. code must be
static DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = {
sizeof(DEV_BROADCAST_DEVICEINTERFACE),
DBT_DEVTYP_DEVICEINTERFACE,
0,
GUID_DEVINTERFACE_VOLUME
};
m_hDevNotify = RegisterDeviceNotification(m_statusHandle,
&NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);
note than need use GUID_DEVINTERFACE_VOLUME
if you want volume arrival/removal notification but not GUID_DEVCLASS_VOLUME
(you use it as { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };
). with GUID_DEVCLASS_VOLUME
you never got notifications, because this is not interface guid. you got notifications only because use set DEVICE_NOTIFY_ALL_INTERFACE_CLASSES
flag - Notifies the recipient of device interface events for all device interface classes. (The dbcc_classguid member is ignored.)
then in handler - you must got dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE
type of notification (not DBT_DEVTYP_VOLUME
) also will be dbcc_classguid == GUID_DEVINTERFACE_VOLUME
if you register exactly for GUID_DEVINTERFACE_VOLUME
only. so you can cast lpEventData
to PDEV_BROADCAST_DEVICEINTERFACE
and use dbcc_name
member - this is win32 symbolic link to volume name (can be used in call CreateFileW
)