1

Please see Edit below.

I am attempting to get the class/interface GUID of a connected device such as a TV or projector. I am using the function RegisterDeviceNotification() to give me the GUID when a TV is connected.

My Problem: When the TV is connected I can successfully be notified but when I go to access the GUID of the device(by inspecting the lParam structure) I get an access violation or error.

I cant figure out whats going wrong? Whenever I go to access or use the GUID my program fails, note my program doesn't crash but the output window writes something like First-chance exception at 0x001c1a9d in myProgram.exe... and I cant figure out whats going wrong?

HDEVNOTIFY *hDeviceNotify;
GUID interfaceClassGuid = { 0x25dbce51, 0x6c8f, 0x4a72, 0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 };
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
        case WM_CREATE:
        {                  
             openConsoleWindow();

             DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
             ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
             NotificationFilter.dbcc_size       = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
             NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
             NotificationFilter.dbcc_classguid  = interfaceClassGuid;

             *hDeviceNotify = RegisterDeviceNotification( hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE );

             if (*hDeviceNotify == NULL)
                 printf("hDeviceNotify = NULL \n");
        }    
        break;
        case WM_DEVICECHANGE:
        {
            PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) lParam;

            // The following printf NEVER prints out. 
            // When accessing the below GUID I get an error:
            // "First-chance exception at 0x001c1a9d in myProgram.exe: 0xC0000005: Access violation writing location 0x00000000."
            printf("GUID: Data1: %x, Data2: %x, Data3: %x, Data4: %s \n", b->dbcc_classguid.Data1,
                b->dbcc_classguid.Data2, b->dbcc_classguid.Data3, (char*)b->dbcc_classguid.Data4);

            // The following function ALWAYS fails.
            // GetLastError() gives the error "The parameter is incorrect"
            HDEVINFO hDevInfo = SetupDiGetClassDevs(&b->dbcc_classguid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
            if (hDevInfo == INVALID_HANDLE_VALUE) {
               //printf("hDevInfo == INVALID_HANDLE_VALUE \n");
               outputLastError(_T("hDevInfo == INVALID_HANDLE_VALUE \n"));
            }

        }
        break;
        ...

Edit: I've applied Hans' advice but still the same issue occurs(printf() never prints and the exception occurs):

        case WM_DEVICECHANGE:
        {
            if (wParam != DBT_DEVNODES_CHANGED) {
                printf("1: \n");
                break;
            }

            PDEV_BROADCAST_HDR h = (PDEV_BROADCAST_HDR) lParam;
            if (h->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE) {
                printf("2\n");
                break;
            }

            PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) h;

            // When accessing the below GUID I get an error:
            // "First-chance exception at 0x001c1a9d in TEST GUID Error.exe: 0xC0000005: Access violation writing location 0x00000000."
            printf("GUID: Data1: %x, Data2: %x, Data3: %x, Data4: %s \n", b->dbcc_classguid.Data1,
                b->dbcc_classguid.Data2, b->dbcc_classguid.Data3, (char*)b->dbcc_classguid.Data4);

            // The following function ALWAYS fails.
            // GetLastError() gives the error "The parameter is incorrect"
            HDEVINFO hDevInfo = SetupDiGetClassDevs(&b->dbcc_classguid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
            if (hDevInfo == INVALID_HANDLE_VALUE) {
               //printf("hDevInfo == INVALID_HANDLE_VALUE \n");
               outputLastError(_T("hDevInfo == INVALID_HANDLE_VALUE \n"));
            }

        }
        break;
sazr
  • 24,984
  • 66
  • 194
  • 362
  • What's that `(char *)` cast doing there? If `UNICODE` is defined, casting it to `char *` won't help. If it isn't defined, that cast doesn't need to be there and only raises suspicion. – chris Jan 05 '13 at 02:57
  • @chris I thought I needed to convert the byte array to a char to print it. I'll remove it but I dont think this is causing the issue – sazr Jan 05 '13 at 04:17
  • According to the documentation, it's a `TCHAR[1]`, so it already decays to a `char *` when you pass it in, assuming no `UNICODE`. – chris Jan 05 '13 at 04:19
  • Wait, are you assigning `hDeviceNotify` before dereferencing it? That would be bad if not. – chris Jan 05 '13 at 04:22
  • You are going to fast. You must first verify that wParam == DBT_DEVICEARRIVAL. Then cast lParam to DEV_BROADCAST_HDR. To check if its dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE. Then you can cast lParam to DEV_BROADCAST_DEVICEINTERFACE. – Hans Passant Jan 05 '13 at 05:48
  • @HansPassant thanks for the comment. Why does it have to be DBT_DEVICEARRIVAL because whenever I connect to a TV the only wParam value is DBT_DEVNODES_CHANGED for both connection and removal? – sazr Jan 05 '13 at 05:59
  • 1
    @JakeM- docs for [DBT_DEVNOTES_CHANGED](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363211(v=vs.85).aspx) state that lParam is 0 in that case, so `h` is NULL, and `h->dbch_devicetype` is dereferencing NULL causing that exception - DBT_DEVICEARRIVAL and DBT_DEVNODESCHANGED are not interchangable. Unfortunately this doesn't get you closer to the information you want, but does explain that exception... – BrendanMcK Jan 07 '13 at 16:41

0 Answers0