Доброго времени суток! Вообщем задача у меня была такой: нужно было перехватить данные, идущие от usb-устройства к драйверу SKUsb.sys, который обслуживает это устройство. Устройство посылает bulk-пакеты, т.е. массив данных. Я написал фильтр-драйвер и вставил его в стек устройств между USBD и SKUsb.sys. Данные прекрасно перехватываются. Чтобы это проверить я использовал KdPrint. Сообственно сам вопрос: как теперь эти данные передать пользовательскому приложению? Сами данные хранятся в массиве. Объвлен он глобально, а не вструктуре расширения устройства. Пробовал поставить обработчик на IRP_MJ_READ и IRP_MJ_DEVICE_CONTROL чтобы пользоваться функциями: ReadFile - для считывания данных; DeviceIoControl - чтобы управлять фильтр-драйвером. И ещё обработчик IRP_MJ_CREATE, IRP_MJ_CLOSE - чтобы пользовательское приложение могло получить/освободить описатель. В итоге получилось следующее: в пользовательском приложении CreateFile выполняется успешно, а вот ReadFile - данная функция не поддерживается устройством. DeviceIoControl - что-то неверное). Пробовал в драйвере натыкать KdPrint`в в начале каждого обработчика, чтобы проверить как они вызываются... Как оказалось ОНИ ВООБЩЕ НЕ ВЫЗЫВАЮСЯ! даже обработчики на IRP_MJ_CREATE и IRP_MJ_CLOSE. Однако если не поставить обработчик на IRP_MJ_CREATE и IRP_MJ_CLOSE, то описатель получить вообще не получается! Вот отрывки кода: Код (Text): Из DriverEntry DriverObject->DriverUnload = DriverUnload; DriverObject->DriverExtension->AddDevice = AddDevice; for (int i = 0; i < arraysize(DriverObject->MajorFunction); ++i) DriverObject->MajorFunction[i] = DispatchAny; DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateDevice; DriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseDevice; DriverObject->MajorFunction[IRP_MJ_READ] = ReadDevice; DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; //Диспетчер энергобережения DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; //Диспетчер PnP DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi; //Диспетчер WMI DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalIOCTL; Из AddDevice 1. Создаем объект устройства: Код (Text): IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &fido); 2. Пристыковываем его стеку устройств: Код (Text): // Вставляем фильтр драйвер в стек нижележайшего драйвера PDEVICE_OBJECT fdo = IoAttachDeviceToDeviceStack(fido, pdo); pdx->LowerDeviceObject = fdo; ясно что pdx - это указатель на структуру DEVICE_EXTENSION fido->Flags |= fdo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH); fido->DeviceType = fdo->DeviceType; fido->Characteristics = fdo->Characteristics; fido->AlignmentRequirement = fdo->AlignmentRequirement; fido->Flags &= ~DO_DEVICE_INITIALIZING; 3. Создаём симольную ссылку. status = IoCreateSymbolicLink (&LinkName, &devName); if (!NT_SUCCESS(status))return status; Еще один момент т.к. данные приходят последовательно, то приходится ждать пока массив не заполнится и только после этого он должен передаваться пользовательскому приложению. Можно ли поставить для этого событие и ожидать в обработчике IRP_MJ_READ пока массив не заполнится?
Код открытия и шо хранится в devName, linkName перепроверь, т.е. правильно ObjManager находит твой устройство, может быть он другое находит ?
Нет тут 100% такой глупой ошибки быть не может. Открывается именно моё устойство. А NTDevices правильно отображает имена devName и LinkName.
RedField Вообще-то для чтения/записи данных в данном случае используется простой обработчик IRP_MJ_DEVICE_CONTROL - через посылку IOCTL из юзермода можно наладить нормальный взаимообмен данными. Чё огород городить? Тем более что в сети примеров полно. Если не устраивает такой вариант, можно тупо сбросить данные на диск после заполнения массива и затем считывать его из юзермода, но это не есть гуд. В конце концов можно, к примеру, из драйвера записать массив в АП твоего процесса, а затем из самого приложения прочесть их.
Тут проблема та в том, что у меня вообще не получается взаимодействовать с драйвером. Как я уже писал если поставить обработчик на IRP_MJ_CREATE, то можно получить описатель в user mode. Но сам то обработчик не вызывается! А если писать в память пользовательского приложения, то тут нужно сначало драйверу получить описатель (HANDLE) этого процесса чтобы потом получить указатель на структуру KPROCESS и потом сделать проецирование системной нестраничной памяти в пользовательское приложение. А как это сделать если драйвер не хочет реагировать на команды из USER MODE? Через реестр передавать... Вообщем этот вариант как самый последний.
файл init.cpp Код (Text): #include "driver.h" #include "usbioctl.h" #include "usbdi.h" #include "usbdlib.h" NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo); VOID DriverUnload (IN PDRIVER_OBJECT fido); NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp); NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp); NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fido, IN PIRP Irp); NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp); NTSTATUS DispatchInternalIOCTL(IN PDEVICE_OBJECT fido, IN PIRP Irp); //------------------------------------------------------------------------------- #pragma INITCODE extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { KdPrint(("MyDriver - Entering DriverEntry: DriverObject %8.8lX\n", DriverObject)); // Операционка должна поддерживать модель драйвера WDM 1.0 и выше if(!IoIsWdmVersionAvailable(1, 0)) { KdPrint(("MyDriver - Expected version of WDM (%d.%2.2d) not available\n", 1, 0)); return STATUS_UNSUCCESSFUL; } // Инициализация основных процедур драйвера DriverObject->DriverUnload = DriverUnload; //Для выгрузки драйвера DriverObject->DriverExtension->AddDevice = AddDevice; //Для использования WDM модели for(int i = 0; i < arraysize(DriverObject->MajorFunction); ++i) DriverObject->MajorFunction[i] = DispatchAny; DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; //Диспетчер энергобережения DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; //Диспетчер PnP DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi; //Диспетчер WMI DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalIOCTL; return STATUS_SUCCESS; } //------------------------------------------------------------------------------- #pragma PAGEDCODE // Процедура выгрузки драйвера VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) { PAGED_CODE(); KdPrint(("MyDriver - Entering DriverUnload: DriverObject %8.8lX\n", DriverObject)); } //------------------------------------------------------------------------------- NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo) { PAGED_CODE(); KdPrint(("MyDriver - Entering AddDevice: DriverObject %8.8lX, pdo %8.8lX\n", DriverObject, pdo)); NTSTATUS status; UNICODE_STRING LinkName, devName; // Создание буферов для имен RtlInitUnicodeString(&LinkName, L"\\DosDevices\\SK_REMOTE"); RtlInitUnicodeString(&devName, L"\\Device\\devSK_REMOTE"); // Создаем объект MyDriver чтобы перехватывать irp-запросы. PDEVICE_OBJECT fido; // Объект фильтра для устройства status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &fido); if (!NT_SUCCESS(status)) { // Объект устройства не был создан KdPrint(("MyDriver - IoCreateDevice failed - %X\n", status)); return status; } // Создание символьного имени драйвера status = IoCreateSymbolicLink (&LinkName, &devName); if (!NT_SUCCESS(status))return status; KdPrint(("MyDriver - Symbolic link")); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; __try { MyIoInitializeRemoveLock(&pdx->RemoveLock, 0, 0, 255); pdx->DeviceObject = fido; pdx->Pdo = pdo; // Вставляем фильтр драйвер в стек нижележайшего драйвера PDEVICE_OBJECT fdo = IoAttachDeviceToDeviceStack(fido, pdo); pdx->LowerDeviceObject = fdo; fido->Flags |= fdo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH); fido->DeviceType = fdo->DeviceType; fido->Characteristics = fdo->Characteristics; fido->AlignmentRequirement = fdo->AlignmentRequirement; fido->Flags &= ~DO_DEVICE_INITIALIZING; } __finally { // В случае сбоя if (!NT_SUCCESS(status)) { // Удаляем фильтр IoDeleteDevice(fido); return status; } } return status; } //------------------------------------------------------------------------------- #pragma LOCKEDCODE NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } //------------------------------------------------------------------------------- #pragma LOCKEDCODE NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); KdPrint(("MyDriver - DispathAny!!!!")); NTSTATUS status; status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp); if (!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0); IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(pdx->LowerDeviceObject, Irp); MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp); return status; } //------------------------------------------------------------------------------- NTSTATUS InternalIOCTLCompletion(IN PDEVICE_OBJECT fido, IN PIRP Irp, IN PVOID Context) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); if(Irp->PendingReturned)IoMarkIrpPending( Irp ); ULONG uSequenceNumber = (ULONG)Context; ULONG dwControlCode = stack->Parameters.DeviceIoControl.IoControlCode; if(IOCTL_INTERNAL_USB_SUBMIT_URB == dwControlCode) { PURB pUrb = (PURB)stack->Parameters.Others.Argument1; // Свой обработчик } return STATUS_SUCCESS; } //------------------------------------------------------------------------------- NTSTATUS DispatchInternalIOCTL(IN PDEVICE_OBJECT fido, IN PIRP Irp) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG dwControlCode = stack->Parameters.DeviceIoControl.IoControlCode; NTSTATUS status; status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp); if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0); if(IOCTL_INTERNAL_USB_SUBMIT_URB == dwControlCode) { ULONG uSequenceNumber = InterlockedIncrement((PLONG)&pdx->uSequenceNumber); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, InternalIOCTLCompletion, (PVOID)uSequenceNumber, TRUE, TRUE, TRUE); status = IoCallDriver(pdx->LowerDeviceObject, Irp); MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp); } else { IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(pdx->LowerDeviceObject, Irp); MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp); } return status; } //------------------------------------------------------------------------------- NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; PoStartNextPowerIrp(Irp); NTSTATUS status; status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp); if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0); IoSkipCurrentIrpStackLocation(Irp); status = PoCallDriver(pdx->LowerDeviceObject, Irp); MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp); return status; } //------------------------------------------------------------------------------- NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp) { PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG fcn = stack->MinorFunction; NTSTATUS status; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp); if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0); IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(pdx->LowerDeviceObject, Irp); if(fcn == IRP_MN_REMOVE_DEVICE) { MyIoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp); RemoveDevice(fido); } else MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp); return status; } //------------------------------------------------------------------------------- NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fido, IN PIRP Irp) { // DispatchWmi NTSTATUS status; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp); if (!NT_SUCCESS(status)) return CompleteRequest(Irp, status, 0); IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(pdx->LowerDeviceObject, Irp); MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp); return status; } //------------------------------------------------------------------------------- #pragma PAGEDCODE VOID RemoveDevice(IN PDEVICE_OBJECT fido) { PAGED_CODE(); UNICODE_STRING LinkName; // Создание буферов для имен RtlInitUnicodeString(&LinkName, L"\\DosDevices\\SK_REMOTE"); KdPrint(("Delete symbolic link")); IoDeleteSymbolicLink(&LinkName); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fido->DeviceExtension; if(pdx->LowerDeviceObject)IoDetachDevice(pdx->LowerDeviceObject); IoDeleteDevice(fido); } //------------------------------------------------------------------------------- #pragma LOCKEDCODE extern "C" void __declspec(naked) __cdecl _chkesp() { _asm je okay ASSERT(!"Stack pointer mismatch!"); okay: _asm ret } файл Driver.h Код (Text): #ifndef _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_ #define _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_ #ifdef __cplusplus extern "C" { #endif #include "wdm.h" #ifdef __cplusplus } #endif /////////////////////////////////////////////////////////////////////////////// #define PAGEDCODE code_seg("page") #define LOCKEDCODE code_seg() #define INITCODE code_seg("init") //------------------------------------------------------------------------------- #define PAGEDDATA data_seg("page") #define LOCKEDDATA data_seg() #define INITDATA data_seg("init") //------------------------------------------------------------------------------- #define arraysize(p) (sizeof(p)/sizeof((p)[0])) //------------------------------------------------------------------------------- #if DBG && defined(_X86_) #undef ASSERT #define ASSERT(e) if(!(e)){DbgPrint("Assertion failure in "\ __FILE__ ", line %d: " #e "\n", __LINE__);\ _asm int 1\ } #endif /////////////////////////////////////////////////////////////////////////////// typedef struct _MY_IO_REMOVE_LOCK { LONG usage; // reference count BOOLEAN removing; // true if removal is pending KEVENT evRemove; // event to wait on } MY_IO_REMOVE_LOCK, *PMY_IO_REMOVE_LOCK; VOID MyIoInitializeRemoveLock(PMY_IO_REMOVE_LOCK lock, ULONG tag, ULONG minutes, ULONG maxcount); NTSTATUS MyIoAcquireRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag); VOID MyIoReleaseRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag); VOID MyIoReleaseRemoveLockAndWait(PMY_IO_REMOVE_LOCK lock, PVOID tag); /////////////////////////////////////////////////////////////////////////////// // Device extension structure typedef struct tagDEVICE_EXTENSION { PDEVICE_OBJECT DeviceObject; // device object this extension belongs to PDEVICE_OBJECT LowerDeviceObject; // next lower driver in same stack PDEVICE_OBJECT Pdo; // the PDO MY_IO_REMOVE_LOCK RemoveLock; ULONG uSequenceNumber; }DEVICE_EXTENSION, *PDEVICE_EXTENSION; /////////////////////////////////////////////////////////////////////////////// // Global functions VOID RemoveDevice(IN PDEVICE_OBJECT fdo); NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info); extern BOOLEAN win98; extern UNICODE_STRING servkey; extern UCHAR CODE[32]; extern ULONG nBytesRead; #endif // DRIVER_H файл RemoveLock.cpp Код (Text): #include "Driver.h" //------------------------------------------------------------------------------- #pragma PAGEDCODE VOID MyIoInitializeRemoveLock(PMY_IO_REMOVE_LOCK lock, ULONG tag, ULONG minutes, ULONG maxcount) { PAGED_CODE(); KeInitializeEvent(&lock->evRemove, NotificationEvent, FALSE); lock->usage = 1; lock->removing = FALSE; } //------------------------------------------------------------------------------- #pragma LOCKEDCODE NTSTATUS MyIoAcquireRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag) { LONG usage = InterlockedIncrement(&lock->usage); if (lock->removing) { // removal in progress if (InterlockedDecrement(&lock->usage) == 0) KeSetEvent(&lock->evRemove, 0, FALSE); return STATUS_DELETE_PENDING; } // removal in progress return STATUS_SUCCESS; } //------------------------------------------------------------------------------- VOID MyIoReleaseRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag) { if (InterlockedDecrement(&lock->usage) == 0) KeSetEvent(&lock->evRemove, 0, FALSE); } //------------------------------------------------------------------------------- #pragma PAGEDCODE VOID MyIoReleaseRemoveLockAndWait(PMY_IO_REMOVE_LOCK lock, PVOID tag) { PAGED_CODE(); lock->removing = TRUE; MyIoReleaseRemoveLock(lock, tag); MyIoReleaseRemoveLock(lock, NULL); KeWaitForSingleObject(&lock->evRemove, Executive, KernelMode, FALSE, NULL); } //------------------------------------------------------------------------------- Файл sources Код (Text): TARGETNAME=UsbSnoop TARGETPATH=obj TARGETTYPE=DRIVER SOURCES= DriverEntry.cpp \ RemoveLock.cpp Файл makefile содержит только строку: !INCLUDE $(NTMAKEENV)\makefile.def
RedField Где-то уже создавали подобную тему. Отсылаю вас к чтению документации по драйверам фильтрам. Потому что некоторые драйверы не позволяют открывать, либо использовать его как нужно манипулятор. Да и вообще есть корректный официальный способ работы с фильтрами. Необходимо создать объект Extra Device Object. Он будет скрывать объект FiDO в стеке PnP. И в функции AddDevice создаются два объекта устройства FiDO который собственно и подключается к стеку PnP, и объект EDO с уникальным именем, но него не подключают к PnP. Ну и символическая ссылка на EDO тоже создается. Вроде уже приводил этот псевдокод. Код (Text): typedef struct _COMMON_DEVICE_EXTENSION { ULONG flag; } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; typedef struct _DEVICE_EXTENSION : public _COMMON_DEVICE_EXTENSION { struct _EXTRA_DEVICE_EXTENSION* edx; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; typedef struct _EXTRA_DEVICE_EXTENSION : public _COMMON_DEVICE_EXTENSION { PDEVICE_EXTENSION pdx; } EXTRA_DEVICE_EXTENSION, *PEXTRA_DEVICE_EXTENSION; #define FIDO_EXTENSION 0 #define EDO_EXTENSION 1 ........ NTSTATUS AddDevice(PDRIVER_OBJECT Driver Object, PDEVICE_OBJECT pdo) { PDEVICE_OBJECT fido; IoCreateDevice(...); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; //other staff pdx->flag = FIDO_EXTENSION; WCHAR namebuf[64]; static LONG numextra = -1; _snwprintf(namebuf, arraysize(namebuf), L"\\Device\\MyExtra%d", InterlockedIncrement(&numextra)); UNICODE_STRING edoname; RtlInitUnicodeString(&ednoname, namebuf); IoCreateDevice(DriverObject, sizeof(EXTRA_DEVICE_EXTENSION), &edoname, FILE_DEVICE_UNKNOWN, 0, FALSE, &edo); PEXTRA_DEVICE_EXTENSION edx = (PEXTRA_DEVICE_EXTENSION) edo->DeviceExtension; edx->flag = EDO_EXTENSION; edx->pdx = pdx; pdx->edx = edx; } В диспетчерской функции указатель на DeviceExtention объекта устройства вначале преобразуется в PCOMMON_DEVICE_EXTENTION, а затем по содержимому поля флагов определяете, к какому объекту предназначен IRP = к FiDO или EDO. Ну и как определили что запрос по EDO - делаете свои действия. Ну и вот и вся хитрость. Все это описано у Walter Oney.
RedField В качестве замечания к коду: В функции функции DispatchAny сделай проверку, какому DEVICE_OBJECT ты пропускаешь IRP, а то получается, что любые IPR, проходящие через твой фильтр ты пересылаешь через IoCallDriver, тогда как IRP, адресованные именно твоему фильтру можно заканчивать вызовом CompleteRequest. Примерно так: Код (Text): NTSTATUS FilterDispatchIo( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine is the dispatch routine for non passthru irps. We will check the input device object to see if the request is meant for the control device object. If it is, we will handle and complete the IRP, if not, we will pass it down to the lower driver. Arguments: DeviceObject - Pointer to the device object. Irp - Pointer to the request packet. Return Value: NT Status code --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; PAGED_CODE(); // // Please note that this is a common dispatch point for controlobject and // filter deviceobject attached to the pnp stack. // if(DeviceObject != ControlDeviceObject) { // We will just the request down as we are not interested in handling // requests that come on the PnP stack. return FilterPass(DeviceObject, Irp); } // // Else this is targeted at our control deviceobject so let's handle it. // Here we will handle the IOCTl requests that come from the app. // status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; irpStack = IoGetCurrentIrpStackLocation (Irp); switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: DebugPrint(("Create \n")); break; case IRP_MJ_CLOSE: DebugPrint(("Close \n")); break; case IRP_MJ_CLEANUP: DebugPrint(("Cleanup \n")); break; case IRP_MJ_DEVICE_CONTROL: DebugPrint(("DeviceIoControl\n")); switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { // //case IOCTL_CUSTOM_CODE: // default: status = STATUS_INVALID_PARAMETER; break; } default: break; } Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; }
Получилось! Содержимое файла Driver.h Код (Text): /////////////////////////////////////////////////////////////////////////////// // Device extension structure typedef struct _COMMON_DEVICE_EXTENSION{ ULONG flag; }COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; typedef struct _DEVICE_EXTENSION: public _COMMON_DEVICE_EXTENSION { struct _EXTRA_DEVICE_EXTENSION* edx; PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT LowerDeviceObject; // next lower driver in same stack PDEVICE_OBJECT Pdo; // the PDO MY_IO_REMOVE_LOCK RemoveLock; ULONG uSequenceNumber; }DEVICE_EXTENSION, *PDEVICE_EXTENSION; typedef struct _EXTRA_DEVICE_EXTENSION: public _COMMON_DEVICE_EXTENSION{ PDEVICE_OBJECT DeviceObject; PDEVICE_EXTENSION pdx; }EXTRA_DEVICE_EXTENSION, *PEXTRA_DEVICE_EXTENSION; #define FIDO_EXTENSION 0 #define EDO_EXTENSION 1 Структура _COMMON_DEVICE_EXTENSION нужна, чтобы в структурах расширения обоих устройств было общее поле flag по которому можно определить к какому объекту устройства принадлежит пакет IRP . Если flag == FIDO_EXTENSION, то посылаем IRP ниже по стеку, а если flag == EDO_EXTENSION - то IRP адресован нам. Создание объектов устройств (проверку на ошибки я опустил): Код (Text): PDEVICE_OBJECT fido; // Объект фильтра для устройства PDEVICE_OBJECT edo; // Именнованный объект устройства status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &fido); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; pdx->flag = FIDO_EXTENSION; ... status = IoCreateDevice(DriverObject, sizeof(EXTRA_DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &edo); PEXTRA_DEVICE_EXTENSION edx = (PEXTRA_DEVICE_EXTENSION) edo->DeviceExtension; edx->flag = EDO_EXTENSION; ... // Создание символьного имени драйвера status = IoCreateSymbolicLink (&LinkName, &devName); Теперь как определить кому адресован IRP!!! В DispatchAny обрабатываются IRP_MJ_READ/IRP_MJ_CREATE/IRP_MJ_CLOSE и др. Чтобы узнать к какому объекту устройства адресован IRP - пакет, нужно явно привести указатель на структуру расширения устройства к одному из типов: PDEVICE_EXTENSION или PEXTRA_DEVICE_EXTENSION и затем по полю flag определить кому адресован IRP. Пример: Код (Text): NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension; if(pdx->flag==FIDO_EXTENSION) { // Пакет адресован фильтр-драйверу. Тут мы можем зарегистрировать свою // процедуру завершения и обязательно передать IRP - пакет ниже по стеку. ... } else { // Пакет адресован нам, т.е. в моем случае он был послан из оконного приложения ... } } При этом получается, что если пакет послан объекту утройства edo, а мы его приобразуем к PDEVICE_EXTENSION, то никаких недорозумений не произойдет если мы обратимся к полю flag, но большой ошибкой будет обращение к другим полям этой структуры. Это произойдет так как структуры отличаются. Пример: struct A struct B { { int n; char flag; char flag; char ch2; }; }; B b; A *pA = (A*)&b; pA->ch = 'E'; // То есть тут мы вообще вышли за границы структуры // и пишем данные неизвестно куда Для этого и нужна структуру котрая потом наследуется другими структурами расширения. Можно конечно расположите flag в структуре A как первое поле, но кто знает как на это отреагирует компилятор. Другой способ как определить кому адресован запрсов. Можно создать глобальную переменную (что не рекомендуется) и в ней хранить указатель одного из объектов устройства. Код (Text): PDEVICE *pp; ... pp = fido; ... NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp) { if(pp == fido) { // адресован fido } else { // адресован нам } }