0

我正在编写一个应该从 cdrom 读取文件并找到特定文件的程序。我订阅了WM_DEVICECHANGE,用于 CdRom 设备并获取DBT_CUSTOMEVENT, DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE消息。

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;
}

但是当我运行我的程序并插入 cdrom 时,我看不到磁盘内容,我看到类似的东西, 程序工作 当我停止调试 cdrom 内容更改为时它是错误的在此处输入图像描述 而且我不知道为什么会发生这种情况,当我调试我的程序时我注意到一个事实,在我插入磁盘后,我收到一条 DBT_DEVICEREMOVECOMPLETE 消息。我认为我的问题在于处理消息功能或打开的句柄,这不允许系统正确读取磁盘内容。谢谢你的帮助。

4

0 回答 0