Фильтр драйвера и DeviceIoControl
От: PR0m  
Дата: 23.09.04 10:09
Оценка:
Всем привет.

Сразу оговорюсь — в области драйверов я новичок
Пишу верхний фильтр (WDM) для устройства с использованием DriverWorks3.1.
Первым делом решил попробовать поуправлять внутренними переменными класса-устройства
RWHookDevice : public KWdmFilterDevice{... private: DWORD m_dwTest; ...};
через DeviceIoControl(...). Определил два кода — один для записи этой переменной, другой для чтения:

#define RWHOOKDRIVER_IOCTL_801 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define RWHOOKDRIVER_IOCTL_802 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)


Хэндлер для DeviceControl(KIrp I) выглядит так:

#define RWHOOKDRIVER_IOCTL_801    0x801
#define RWHOOKDRIVER_IOCTL_802    0x802

NTSTATUS RWHookDevice::DeviceControl(KIrp I)    
{ 
    NTSTATUS status;
    char bPassToLowerDev = 0;

    t <<"Entering RWHookDevice::DeviceControl\n";

    switch (I.IoctlCode())
    {
    // Свои управляющие коды обслуживаем на месте и сразу завершаем IRP
        case RWHOOKDRIVER_IOCTL_801:
            status = RWHOOKDRIVER_IOCTL_801_Handler(I);
            break;

        case RWHOOKDRIVER_IOCTL_802:
            status = RWHOOKDRIVER_IOCTL_802_Handler(I);
            break;

    // Остальные упр.коды отправляем ниже
        default:
            bNotPassToLowerDev = 1;
            status = PassThrough(I);
            break;
    }

    if( !bPassToLowerDev )
        return I.PnpComplete(status);
    else
        return status;
}



Хэндлеры для кодов RWHOOKDRIVER_IOCTL_801,RWHOOKDRIVER_IOCTL_802:

///////////////////////////////////////////////////////////////////////
// Чтение m_dwTest
///////////////////////////////////////////////////////////////////////
NTSTATUS RWHookDevice::RWHOOKDRIVER_IOCTL_801_Handler(KIrp I)
{
    NTSTATUS status = STATUS_SUCCESS;

    t << "Entering TestDriverDevice::RWHOOKDRIVER_IOCTL_801_Handler, " << I << "\n";

    if( I.IoctlOutputBufferSize() < sizeof(DWORD) )
        return STATUS_INVALID_PARAMETER;

    DWORD* pOutBuf = (DWORD*)I.IoctlBuffer();
    if( pOutBuf != NULL )
    {
        *pOutBuf = m_dwTest;
        I.Information() = sizeof(DWORD);
    }
    else
    {
        t << "NULL out buffer pointer!!!\n";
        I.Information() = 0;
        status = STATUS_INVALID_PARAMETER;
    }
    return status;
}

///////////////////////////////////////////////////////////////////////
// Запись m_dwTest
///////////////////////////////////////////////////////////////////////
NTSTATUS RWHookDevice::RWHOOKDRIVER_IOCTL_802_Handler(KIrp I)
{
    t << "Entering TestDriverDevice::RWHOOKDRIVER_IOCTL_802_Handler, " << I << "\n";

    if( I.IoctlInputBufferSize() < sizeof(DWORD) )
        return STATUS_INVALID_PARAMETER;

    DWORD* pOutBuf = (DWORD*)I.IoctlBuffer();

    if( pOutBuf == NULL )
    {
        t << "NULL in buffer pointer!!!\n";
        I.Information() = 0;
        return STATUS_INVALID_PARAMETER;
    }

    m_dwTest = *pOutBuf;
    I.Information() = 0;

    return STATUS_SUCCESS;
}


Для user-mode приложения определил пару функций:
FILTERDLL_API BOOL RwhWriteTestValue(HANDLE hDevice,DWORD dwValue)
{
    if( hDevice == INVALID_HANDLE_VALUE )
        return FALSE;
    OVERLAPPED ovl = {0};
    BOOL bRes = FALSE;
    DWORD dwBytesReturned;

    __try
    {
        ovl.hEvent = ::CreateEvent(NULL,TRUE,FALSE,NULL);
        bRes = ::DeviceIoControl(
            hDevice,
            RWHOOKDRIVER_IOCTL_802,
            &dwValue,
            sizeof(DWORD),
            NULL,
            0,
            &dwBytesReturned,&ovl);
    }
    __finally
    {
        ::CloseHandle(ovl.hEvent);
    }
    return bRes;
}

FILTERDLL_API BOOL RwhReadTestValue(HANDLE hDevice,LPDWORD pdwValue)
{
    if( hDevice == INVALID_HANDLE_VALUE )
        return FALSE;

    OVERLAPPED ovl = {0};
    BOOL bRes = FALSE;
    DWORD dwValue,dwBytesReturned;

    __try
    {
        ovl.hEvent = ::CreateEvent(NULL,TRUE,FALSE,NULL);
        bRes = ::DeviceIoControl(
            hDevice,
            RWHOOKDRIVER_IOCTL_801,
            NULL,
            0,
            &dwValue,
            sizeof(DWORD),
            &dwBytesReturned,
            &ovl);
        if( bRes )
            *pdwValue = dwValue;
    }
    __finally
    {
        ::CloseHandle(ovl.hEvent);
    }
    return bRes;
}


А проблема собстно в том, что запись проходит успешно, а при чтении выводится отладочное сообщение из драйвера
"NULL out buffer pointer!!!\n" ..., то бишь почему-то в драйвер не передаётся адрес выходного буфера, куда нужно вернуть значение
m_dwTest.
Работаю под WinXP SP2. Пробовал компилить под DDK_2K и DDK_XP с одинаковым результатом. С установкой и удалением фильтра проблем нет.
Ставлю на communications Port (COM-порты).

Где ж тут собака закопана?

С уважением, Роман.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.