Всем привет.
Сразу оговорюсь — в области драйверов я новичок

Пишу верхний фильтр (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-порты).
Где ж тут собака закопана?
С уважением, Роман.