Показать сообщение отдельно
  (#1 (permalink)) Старый
imported_Cybernetic imported_Cybernetic вне форума
Новичок
 
Сообщений: 3
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 01.06.2005
По умолчанию Проблема с передачей буфера данных в драйвер - 01.06.2005, 13:01

Всем здравствуйте. Вопрос такой: имеется простейший драйвер-фильтр, работающий под nt из
книги Павла Агурова "Интерфейс USB".
Ниже привожу его текст:
Код:
#include <ntddk.h>
#include "testdrv.h"

// Имя нашего драйвера устройства 
#define DEVICE_NAME_STRING L"testdriver"


// Заголовки функций-обработчиков
VOID OnUnloadHandle(IN PDRIVER_OBJECT);
NTSTATUS IrpHandler(IN PDEVICE_OBJECT, IN PIRP);
NTSTATUS OnDeviceControlHandle(IN PDEVICE_OBJECT, IN PIRP);

NTSTATUS OnAddDeviceHandle(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);

/* ============================================================
Точка входа в драйвер. Выполняется при загрузке.
============================================================ */
void TestDriver(void)
{
 DbgPrint("TestDriver");
}

/* ============================================================
Процедура входа драйвера. Эта процедура вызывается только раз 
после загрузки драйвера в память. 
============================================================ */
NTSTATUS DriverEntry(
 IN PDRIVER_OBJECT DriverObject,
 IN PUNICODE_STRING RegistryPath
)
{
 PDEVICE_OBJECT deviceObject;
 NTSTATUS status;
 int i;

 WCHAR NameBuffer[] = L"Device" DEVICE_NAME_STRING;
 WCHAR DOSNameBuffer[] = L"DosDevices" DEVICE_NAME_STRING;
 UNICODE_STRING uniNameString, uniDOSString;

 DbgPrint("DriverEntry");

 // Создание буферов для имен
 RtlInitUnicodeString(&uniNameString, NameBuffer);
 RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);

 // Инифиализация объекта драйвера
 status = IoCreateDevice(DriverObject, 0, &uniNameString,
   FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);
 if(!NT_SUCCESS(status))
  return status;

 // Создание символьного имени драйвера
 status = IoCreateSymbolicLink (&uniDOSString, &uniNameString);
 if (!NT_SUCCESS(status))
  return status;

 // Инициализируем точки входа драйвера в объекте 
 // драйвера. 
 for (i=0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
  DriverObject->MajorFunction[i]= IrpHandler;
 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OnDeviceControlHandle;
 DriverObject->DriverUnload = OnUnloadHandle;
 DriverObject->DriverExtension->AddDevice = OnAddDeviceHandle;

 return(STATUS_SUCCESS);
}

/* ============================================================
Вызывается при вызове CreateProcess() из пользовательского
режима работы. Адрес этой процедуры был зарегистрирован в 
процедуре DriverEntry, как обработчик рабочей процедуры 
IRP_MJ_CREATE.
============================================================ */
NTSTATUS OnAddDeviceHandle(
 IN PDRIVER_OBJECT DriverObject,
 IN PDEVICE_OBJECT PhysicalDeviceObject 
)
{
 DbgPrint("OnAddDeviceHandle");
 return(STATUS_SUCCESS);
}

/* ============================================================
Вызывается при обработке любой рабочей процедуры, кроме
процедуры IRP_MJ_DEVICE_CONTROL, обрабатываемой отдельно
============================================================ */
NTSTATUS IrpHandler(
 IN PDEVICE_OBJECT DeviceObject,
 IN PIRP Irp
)
{
 DbgPrint("IrpHandle");

 // Завершение обработки
 Irp->IoStatus.Information = 0;
 Irp->IoStatus.Status = STATUS_SUCCESS;
 IoCompleteRequest(Irp, IO_NO_INCREMENT);
 return STATUS_SUCCESS;
}

/* ============================================================
Вызывается при выгрузке драйвера. Адрес этой процедуры
был зарегистрирован в процедуре DriverEntry, как обработчик
события DriverUnload.
============================================================ */
VOID OnUnloadHandle(IN PDRIVER_OBJECT DriverObject)
{
 // Символьное имя драйвера
 WCHAR DOSNameBuffer[] = L"DosDevices" DEVICE_NAME_STRING;
 UNICODE_STRING uniDOSString;

 DbgPrint("OnUnloadHandle");

 // Инициализация буфера для символьного имени
 RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);
 // Удаление символьного имени
 IoDeleteSymbolicLink (&uniDOSString);
 // Удаление объекта драйвера
 IoDeleteDevice(DriverObject->DeviceObject);
}


/* ============================================================
Вызывается при вызове DeviceIoControl из пользовательского
режима работы. Адрес этой процедуры был зарегистрирован в 
процедуре DriverEntry, как обработчик рабочей процедуры 
IRP_MJ_DEVICE_CONTROL.
============================================================ */
NTSTATUS OnDeviceControlHandle(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP pIrp
    )

{
 NTSTATUS            ntStatus = STATUS_SUCCESS;   
 PIO_STACK_LOCATION  irpSp;

 // Длина входного буфера      
 ULONG  inBufLength;   
 // Длина выходного буфера     
 ULONG  outBufLength;  
 // Указатель на входной и выходной буфер 
 PULONG ioBuffer;      

 DbgPrint("OnDeviceControlHandle");

 // Указатель на драйверный стек
 irpSp= IoGetCurrentIrpStackLocation(pIrp);

 // Входной и выходной буфкра и их длины
 inBufLength  = irpSp->Parameters.DeviceIoControl.InputBufferLength;
 outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
 ioBuffer     = (PULONG) pIrp->AssociatedIrp.SystemBuffer;

 switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
 {
  // обработка кода функции IOCTL_IOPM_FUNCTION1
  case IOCTL_IOPM_FUNCTION1:
  {
   if (inBufLength > 0) {
    DbgPrint(">IOCTL_IOPM_FUNCTION1");
    ioBuffer[0]++;
   }
   break;
  }
  // обработка кода функции IOCTL_IOPM_FUNCTION2
  case IOCTL_IOPM_FUNCTION2:
  {
   if (inBufLength > 0) {
    DbgPrint(">IOCTL_IOPM_FUNCTION2");
    ioBuffer[0]--;
   }
   break;
  }
 }

 // Завершение рабочей процедуры
 pIrp->IoStatus.Information = inBufLength; /* Размер выходного буфера */
 pIrp->IoStatus.Status = ntStatus;
 IoCompleteRequest( pIrp, IO_NO_INCREMENT );
 return ntStatus;
}
В качестве обработчика irp всех запросов исползуется 1-а и та же ф-я IrpHandler.
Драйвер "отфильтровывает" вызовы только 2-х функций: IOCTL_IOPM_FUNCTION1 и IOCTL_IOPM_FUNCTION2
DeviceioControl. Метод передачи данных буферизованный.
При вызове функции IOCTL_IOPM_FUNCTION1 драйвер увеличивает значение переданного элемента буфера на 1.
При вызове IOCTL_IOPM_FUNCTION2 - уменьшает на 1.
А теперь вопрос: В этом примере при передаче используется буфер размером в 1-н элемент. А мне нужно передать массив данных в котором бы было более 1-го элемента.
Вроде бы, ну что мне мешает. Взял и передал. И обращаюсь уже не к IoBuffer[0], а к примеру к IoBuffer[7]. Но в том то всё и загвоздка - он(драйвер) почему-то не хочет видеть все, отличные от 0-го элементы массива... Обращаешься к IoBuffer[не ноль],
а там записана какая-то произвольная чушь из памяти...
Пользовательское приложение для работы с этим драйвером у меня написано на delphi (вернее у Павла Агурова написано ). Но в форум
программирования на делфях обращаться не стал, так как думаю, что причина всё же в драйвере. В программе на delphi всё предельно ясно: вызвали DeviceIoControl и передали
ей входной буфер, какие там могут быть ошибки...
Ответить с цитированием
Ads