3

I am trying to detect a USB disk drive being inserted within a Windows Service, I have done this as a normal Windows application. The problem is the following code doesn't work for volumes.

Registering the device notification:

    DEV_BROADCAST_DEVICEINTERFACE notificationFilter;
    HDEVNOTIFY hDeviceNotify = NULL;        

    ::ZeroMemory(&notificationFilter, sizeof(notificationFilter));

    notificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    notificationFilter.dbcc_classguid = ::GUID_DEVINTERFACE_VOLUME;

    hDeviceNotify = ::RegisterDeviceNotification(g_serviceStatusHandle, &notificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);

The code from the ServiceControlHandlerEx function:

case SERVICE_CONTROL_DEVICEEVENT:
    PDEV_BROADCAST_HDR pBroadcastHdr = (PDEV_BROADCAST_HDR)lpEventData;

    switch (dwEventType)
    {
    case DBT_DEVICEARRIVAL:
        ::MessageBox(NULL, "A Device has been plugged in.", "Pounce", MB_OK | MB_ICONINFORMATION);

        switch (pBroadcastHdr->dbch_devicetype)
        {
        case DBT_DEVTYP_DEVICEINTERFACE:
            PDEV_BROADCAST_DEVICEINTERFACE pDevInt = (PDEV_BROADCAST_DEVICEINTERFACE)pBroadcastHdr;

            if (::IsEqualGUID(pDevInt->dbcc_classguid, GUID_DEVINTERFACE_VOLUME))
            {
                PDEV_BROADCAST_VOLUME pVol = (PDEV_BROADCAST_VOLUME)pDevInt;

                char szMsg[80];
                char cDriveLetter = ::GetDriveLetter(pVol->dbcv_unitmask);

                ::wsprintfA(szMsg, "USB disk drive with the drive letter '%c:' has been inserted.", cDriveLetter);
                ::MessageBoxA(NULL, szMsg, "Pounce", MB_OK | MB_ICONINFORMATION);
            }
        }

        return NO_ERROR;
    }

In a Windows application I am able to get the DBT_DEVTYP_VOLUME in dbch_devicetype, however this isn't present in a Windows Service implementation. Has anyone seen or heard of a solution to this problem, without the obvious, rewrite as a Windows application?

James McNellis
  • 348,265
  • 75
  • 913
  • 977
Tom Bell
  • 1,120
  • 2
  • 16
  • 33
  • What exactly isn't working? I did this a few months ago and managed to get it working. – Luke Apr 14 '10 at 16:32
  • 1
    I've looked at this before and couldn't get DBT_DEVTYP_VOLUME either. Checking the GUID is the workaround I used, just like you're doing. I'm probably being thick, but what are you trying to achieve that checking the GUID doesn't give you? – snowcrash09 Apr 14 '10 at 16:49
  • 1
    I just noticed that you are casting it as a DEV_BROADCAST_VOLUME; this is wrong. It is a DEV_BROADCAST_DEVICEINTERFACE and you must get the drive name from the device name. – Luke Apr 14 '10 at 17:02

1 Answers1

2

Windows 7 supports "trigger started services". If you want to start your service, go around in a sleeping loop, and react whenever something is plugged in, I think you would be better off (assuming Windows 7 is an option) going with a trigger started service where the OS starts the service when a USB device is plugged in. (There are other triggers but you mentioned this one.)

The sample application XP2Win7 (http://code.msdn.microsoft.com/XP2Win7) includes this functionality. It comes with full source code. Most is in VB and C# but the trigger started services part is in (native) C++.

Kate Gregory
  • 18,808
  • 8
  • 56
  • 85