0

I'm writing a program that should read files from cdrom and finds specific files. I subscribed to WM_DEVICECHANGE, for CdRom Device and get DBT_CUSTOMEVENT, DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE messages.

DWORD OpenDevNotify(SCANNING_DRIVE* pDesc, HANDLE hReceiver, bool isService)
{
    if (pDesc->hDevice == nullptr || pDesc->hDevice == INVALID_HANDLE_VALUE)
        return ERROR_INVALID_PARAMETER;
    DEV_BROADCAST_HANDLE NotificationFilter;
    RtlZeroMemory(&NotificationFilter, sizeof(DEV_BROADCAST_HANDLE));
    NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
    NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
    NotificationFilter.dbch_handle = pDesc->hDevice;
    DWORD Flag = isService ? DEVICE_NOTIFY_SERVICE_HANDLE : DEVICE_NOTIFY_WINDOW_HANDLE;
    pDesc->hDevNotify = RegisterDeviceNotification(hReceiver, &NotificationFilter, Flag);
    if (pDesc->hDevNotify == nullptr)
        return GetLastError();
    return 0;
}

DWORD OpenDeviceHandle(SCANNING_DRIVE* pDesc, const wchar_t* RootFolder)
{
    std::wstring RootFolderPattern(L"\\\\.\\");
    RootFolderPattern.append(RootFolder);
    pDesc->hDevice = CreateFile(RootFolderPattern.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
        nullptr, OPEN_EXISTING, 0, nullptr);
    if (pDesc->hDevice == INVALID_HANDLE_VALUE)
        return GetLastError();
    return 0;
}

SCANNING_DRIVE RegisterForDeviceNotifications(const wchar_t* RootFolder, HANDLE hReceiver, bool isService)
{
    SCANNING_DRIVE dsc;
    RtlZeroMemory(&dsc, sizeof(SCANNING_DRIVE));

    DWORD res = OpenDeviceHandle(&dsc, RootFolder);
    if (res != 0)
        return dsc;

    res = OpenDevNotify(&dsc, hReceiver, isService);
    if (res != 0)
        return dsc;

    SetRootDir(&dsc, RootFolder);
    CreateStopEvent(&dsc);

    return dsc;
}

bool OnDeviceArrival(HANDLE hReceiver, WPARAM wParam, LPARAM lparam, BOOL isService)
{
    PDEV_BROADCAST_HDR pdbhdr = nullptr;
    PDEV_BROADCAST_HANDLE pdbh = nullptr;
    PDEV_BROADCAST_VOLUME pdbv = nullptr;
    size_t i = SIZE_MAX;

    switch (wParam)
    {
    case DBT_DEVICEARRIVAL:
        {
        pdbhdr = reinterpret_cast<PDEV_BROADCAST_HDR>(lparam);
        if (pdbhdr == nullptr || pdbhdr->dbch_devicetype != DBT_DEVTYP_VOLUME)
            break;
        pdbv = reinterpret_cast<PDEV_BROADCAST_VOLUME>(lparam);
        auto vol = VolumeLetterFromUnitMask(pdbv->dbcv_unitmask);
        i = GetDeviceIndexFromListByVolumeLetter(vol);
        if (i == SIZE_MAX || g_ConnectedDeviceVector.size() < i)
            break;
        if (g_ConnectedDeviceVector[i].hProcessingThread == INVALID_HANDLE_VALUE || g_ConnectedDeviceVector[i].hProcessingThread == nullptr)
        {
            g_ConnectedDeviceVector[i].hProcessingThread = CreateAndStartScanningThread(&g_ConnectedDeviceVector[i], ProcessDeviceThread);
            //auto a = ResumeThread(g_ConnectedDeviceVector[i].hProcessingThread);
            auto d = GetLastError();
        }
        break;
        }
    case DBT_CUSTOMEVENT:
        {
/*      pdbhdr = reinterpret_cast<PDEV_BROADCAST_HDR>(lparam);
        if (pdbhdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
            break;
        pdbh = reinterpret_cast<PDEV_BROADCAST_HANDLE>(lparam);
        i = GetDeviceIndexFromListByHandle(pdbh->dbch_handle);
        if (i == SIZE_MAX || g_ConnectedDeviceVector.size() < i)
            break;
        if (IsEqualGUID(pdbh->dbch_eventguid, GUID_IO_MEDIA_ARRIVALGUID_IO_MEDIA_ARRIVAL))
        {
            auto cmcc = reinterpret_cast<CLASS_MEDIA_CHANGE_CONTEXT*>(pdbh->dbch_data);
            if (cmcc->NewState == 1) // 1 - Media Present
                g_ConnectedDeviceVector[i].hProcessingThread = CreateScanningThread(&g_ConnectedDeviceVector[i], ProcessDeviceThread);
        }

        if (IsEqualGUID(pdbh->dbch_eventguid, GUID_IO_MEDIA_EJECT_REQUEST) ||
            IsEqualGUID(pdbh->dbch_eventguid, GUID_IO_MEDIA_REMOVAL))
        {
            StopScanningThread(&g_ConnectedDeviceVector[i]);
        }*/
        break;
        }
    case DBT_DEVICEREMOVECOMPLETE:
        {
        pdbhdr = reinterpret_cast<PDEV_BROADCAST_HDR>(lparam);
        if (pdbhdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
            break;
        pdbh = reinterpret_cast<PDEV_BROADCAST_HANDLE>(lparam);
        i = GetDeviceIndexFromListByHandle(pdbh->dbch_handle);
        if (i == SIZE_MAX || g_ConnectedDeviceVector.size() < i)
            break;
        //StopScanningThread(&g_ConnectedDeviceVector[i]);
        }
        break;

    default:
        break;
    }
    return true;
}

But when I runs my programm and inserts cdrom I don't see disk contents, I see something like that Programm working and it's wrong when I stop debugging cdrom contents changing to enter image description here And I don't know why it happens, when I had debugging my program I noted a fact that after I inserted a disk I got a DBT_DEVICEREMOVECOMPLETE message. I think my problem is in processing messages function or opened handle, that don't allows system to read disk contents right. Thank you for help.

byaruhaf
  • 4,128
  • 2
  • 32
  • 50
drem1lin
  • 331
  • 1
  • 3
  • 14
  • Generally, you can receive `DBT_DEVICEREMOVECOMPLETE` device event when a device or piece of media has been **physically removed** instead of **inserted**. Could you confirm if you received `DBT_DEVICEQUERYREMOVE` and `DBT_DEVICEREMOVEPENDING` messages with `DBT_DEVICEREMOVECOMPLETE` message? – Rita Han Feb 05 '20 at 02:55
  • Today I did few more tests and now I'm sure, I don't receive another messages except DBT_DEVICEARRIVAL (0x8000) DBT_CUSTOMEVENT(0x8006) and DBT_DEVICEREMOVECOMPLETE (0x8004). To check I saved all WM_DEVICECHANGE wParam codes in global array . – drem1lin Feb 05 '20 at 08:05
  • improved formatting – byaruhaf Feb 05 '20 at 08:29
  • @drem1lin I can't reproduce this issue using a .iso map to a DVD drive. Code as `case DBT_DEVICEARRIVAL: // Check whether a CD or DVD was inserted into a drive. if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) { PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; auto vol = VolumeLetterFromUnitMask(lpdbv->dbcv_unitmask); if (NULL == vol) break; OpenDeviceHandle(vol); } break;` Related official sample: [Detecting Media Insertion or Removal](https://learn.microsoft.com/en-us/windows/win32/devio/detecting-media-insertion-or-removal). – Rita Han Feb 29 '20 at 03:45
  • @drem1lin Can you have a try? (I don't test a hardware real CD device). – Rita Han Feb 29 '20 at 03:46

0 Answers0