Windows Volume Insertion Detection

I've been trying to create a program that detects whenever a new volume is mounted and display the drive letter of the newly inserted drive. I've been trying to use the WM_DEVICECHANGE window message to do this. Currently this is my code:

Media detector class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MediaDetector
{
    private:
        HWND message_handler;
        HDEVNOTIFY device_notify;

        void on_volume_found(char);
    public:
        MediaDetector();
        ~MediaDetector();

        void start();
        void stop();

        void on_device_connected(DWORD);
};


Member functions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//Constructor and destructor
MediaDetector::MediaDetector() : device_notify(NULL)
{
    debug_log("Created media detector");

    WNDCLASSEX window_class = {0};
    window_class.cbSize = sizeof(WNDCLASSEX);
    window_class.lpfnWndProc = media_window_handler;
    window_class.hInstance = GetModuleHandle(nullptr);
    window_class.lpszClassName = MEDIADETECTOR_WINDOW_CLASS_NAME;

    if(RegisterClassEx(&window_class) == 0)
        throw DetectorException("Could not register window class");

    this->message_handler = CreateWindow(MEDIADETECTOR_WINDOW_CLASS_NAME, nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, GetModuleHandle(nullptr), this);
    if(this->message_handler == NULL)
        throw DetectorException("Could not create message handling queue");

}

MediaDetector::~MediaDetector()
{
    debug_log("Destroying media detector");
    DestroyWindow(this->message_handler);
}

//Starting/stopping the detection
void MediaDetector::start()
{
    debug_log("Starting media detector");

    DEV_BROADCAST_DEVICEINTERFACE filter = {0};
    filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;

    this->device_notify = RegisterDeviceNotification(this->message_handler, &filter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
    if(this->device_notify == NULL)
        throw DetectorException("Could not register for device notifications");

}

void MediaDetector::stop()
{
    UnregisterDeviceNotification(this->device_notify);

    this->device_notify = NULL;
}

//Called when a new device is connected
void MediaDetector::on_device_connected(DWORD drive_mask)
{
    debug_log("Media detected detected media");

    for(size_t i = 0; i < 26; ++i)
    {
        if(drive_mask & 0x1)
            this->on_volume_found((char)i);
        drive_mask >>= 1;
    }
}

//Called when a drive letter is found
void MediaDetector::on_volume_found(char drive_letter)
{
    debug_logf("Found volume %c", drive_letter);
}


Window message callback:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//Window callback handling device insertion
LRESULT CALLBACK media_window_handler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    switch(msg)
    {
        case WM_CREATE:
        {
            debug_log("Media detector WM_CREATE");
            LPCREATESTRUCT creation_data = (LPCREATESTRUCT)lparam;
            MediaDetector* media_detector = (MediaDetector*)creation_data->lpCreateParams;
            SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)media_detector);
        }
            break;
        case WM_DEVICECHANGE:
        {
            PDEV_BROADCAST_HDR device_info = (PDEV_BROADCAST_HDR)lparam;
            debug_logf("Detected device type %d", (int)device_info->dbch_devicetype);
            switch(wparam)
            {
                case DBT_DEVICEARRIVAL:
                    debug_log("Media detector detected device insertion");
                    if(device_info->dbch_devicetype == DBT_DEVTYP_VOLUME)
                    {
                        PDEV_BROADCAST_VOLUME volume_info = (PDEV_BROADCAST_VOLUME)device_info;
                        MediaDetector* media_detector = (MediaDetector*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
                        media_detector->on_device_connected(volume_info->dbcv_unitmask);
                    }
                    break;
            }
        }
            break;
        default:
            return DefWindowProc(hwnd, msg, wparam, lparam);
    }
    return 0;
}


And the program entry point:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//Main function
int main()
{
    try
    {
        MediaDetector detector;
        detector.start();

        //Message loop
        MSG msg;
        while(GetMessage(&msg, nullptr, 0, 0) > 0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        detector.stop();
    }
    catch(const DetectorException& e)
    {
        debug_log(e.what());
    }

    return 0;
}


This code currently detects when an USB drive is inserted, but cannot show the drive letter (the device type is DBT_DEVTYP_DEVICEINTERFACE instead of DBT_DEVTYPE_VOLUME, not giving any information on the drive letter). And as of currently it doesn't detect any other hardware volumes inserted (e.g. DVD drives). Even though both the USB as the DVD show up as a new drive in windows explorer.

Is there any way to receive a notification when a new drive is inserted?
Topic archived. No new replies allowed.