Как организовать взаимодействие фильтр-драйвера с оконным приложением?

Тема в разделе "WASM.NT.KERNEL", создана пользователем RedField, 28 май 2010.

  1. RedField

    RedField New Member

    Публикаций:
    0
    Регистрация:
    28 май 2010
    Сообщения:
    8
    Доброго времени суток!

    Вообщем задача у меня была такой: нужно было перехватить данные, идущие от 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):
    1. Из DriverEntry
    2. DriverObject->DriverUnload = DriverUnload;        
    3. DriverObject->DriverExtension->AddDevice = AddDevice;
    4.    
    5.  
    6. for (int i = 0; i < arraysize(DriverObject->MajorFunction); ++i)
    7.      DriverObject->MajorFunction[i] = DispatchAny;
    8.    
    9. DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateDevice;
    10. DriverObject->MajorFunction[IRP_MJ_CLOSE]  = CloseDevice;
    11. DriverObject->MajorFunction[IRP_MJ_READ]   = ReadDevice;
    12.    
    13. DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; //Диспетчер энергобережения
    14. DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;     //Диспетчер PnP
    15. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi; //Диспетчер WMI
    16. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalIOCTL;
    Из AddDevice
    1. Создаем объект устройства:
    Код (Text):
    1. IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &fido);
    2. Пристыковываем его стеку устройств:
    Код (Text):
    1. // Вставляем фильтр драйвер в стек нижележайшего драйвера
    2. PDEVICE_OBJECT fdo = IoAttachDeviceToDeviceStack(fido, pdo);
    3. pdx->LowerDeviceObject = fdo;  ясно что pdx - это указатель на структуру DEVICE_EXTENSION
    4. fido->Flags |= fdo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH);
    5. fido->DeviceType = fdo->DeviceType;
    6. fido->Characteristics = fdo->Characteristics;
    7. fido->AlignmentRequirement = fdo->AlignmentRequirement;
    8. fido->Flags &= ~DO_DEVICE_INITIALIZING;
    9. 3. Создаём симольную ссылку.
    10. status = IoCreateSymbolicLink (&LinkName, &devName);
    11. if (!NT_SUCCESS(status))return status;
    Еще один момент т.к. данные приходят последовательно, то приходится ждать пока массив не заполнится и только после этого он должен передаваться пользовательскому приложению.
    Можно ли поставить для этого событие и ожидать в обработчике IRP_MJ_READ пока массив не заполнится?
     
  2. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    Код открытия и шо хранится в devName, linkName перепроверь, т.е. правильно ObjManager находит твой устройство, может быть он другое находит ? ;)
     
  3. RedField

    RedField New Member

    Публикаций:
    0
    Регистрация:
    28 май 2010
    Сообщения:
    8
    Нет тут 100% такой глупой ошибки быть не может. Открывается именно моё устойство. А NTDevices правильно отображает имена devName и LinkName.
     
  4. JhanGhuangxi

    JhanGhuangxi New Member

    Публикаций:
    0
    Регистрация:
    15 апр 2010
    Сообщения:
    31
    RedField
    Вообще-то для чтения/записи данных в данном случае используется простой обработчик IRP_MJ_DEVICE_CONTROL - через посылку IOCTL из юзермода можно наладить нормальный взаимообмен данными. Чё огород городить? Тем более что в сети примеров полно.
    Если не устраивает такой вариант, можно тупо сбросить данные на диск после заполнения массива и затем считывать его из юзермода, но это не есть гуд. В конце концов можно, к примеру, из драйвера записать массив в АП твоего процесса, а затем из самого приложения прочесть их.
     
  5. RedField

    RedField New Member

    Публикаций:
    0
    Регистрация:
    28 май 2010
    Сообщения:
    8
    Тут проблема та в том, что у меня вообще не получается взаимодействовать с драйвером. Как я уже писал если поставить обработчик на IRP_MJ_CREATE, то можно получить описатель в user mode. Но сам то обработчик не вызывается!
    А если писать в память пользовательского приложения, то тут нужно сначало драйверу получить описатель (HANDLE) этого процесса чтобы потом получить указатель на структуру KPROCESS и потом сделать проецирование системной нестраничной памяти в пользовательское приложение. А как это сделать если драйвер не хочет реагировать на команды из USER MODE? Через реестр передавать... Вообщем этот вариант как самый последний.
     
  6. JhanGhuangxi

    JhanGhuangxi New Member

    Публикаций:
    0
    Регистрация:
    15 апр 2010
    Сообщения:
    31
    Давай, свети весь код, будем умные мысли думать...
     
  7. RedField

    RedField New Member

    Публикаций:
    0
    Регистрация:
    28 май 2010
    Сообщения:
    8
    файл init.cpp
    Код (Text):
    1. #include "driver.h"
    2. #include "usbioctl.h"
    3. #include "usbdi.h"
    4. #include "usbdlib.h"
    5.  
    6. NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo);
    7. VOID DriverUnload (IN PDRIVER_OBJECT fido);
    8. NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    9. NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    10. NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    11. NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    12. NTSTATUS DispatchInternalIOCTL(IN PDEVICE_OBJECT fido, IN PIRP Irp);
    13. //-------------------------------------------------------------------------------
    14. #pragma INITCODE
    15.  
    16. extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
    17. {
    18.     KdPrint(("MyDriver - Entering DriverEntry: DriverObject %8.8lX\n", DriverObject));
    19.    
    20.     // Операционка должна поддерживать модель драйвера WDM 1.0 и выше
    21.     if(!IoIsWdmVersionAvailable(1, 0))
    22.     {
    23.         KdPrint(("MyDriver - Expected version of WDM (%d.%2.2d) not available\n", 1, 0));
    24.         return STATUS_UNSUCCESSFUL;
    25.     }
    26.     // Инициализация основных процедур драйвера
    27.     DriverObject->DriverUnload = DriverUnload;            //Для выгрузки драйвера
    28.     DriverObject->DriverExtension->AddDevice = AddDevice; //Для использования WDM модели
    29.     for(int i = 0; i < arraysize(DriverObject->MajorFunction); ++i)
    30.         DriverObject->MajorFunction[i] = DispatchAny;
    31.     DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; //Диспетчер энергобережения
    32.     DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;     //Диспетчер PnP
    33.     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi; //Диспетчер WMI
    34.     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalIOCTL;
    35.  
    36.     return STATUS_SUCCESS;
    37. }
    38. //-------------------------------------------------------------------------------
    39. #pragma PAGEDCODE
    40. // Процедура выгрузки драйвера
    41. VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
    42. {
    43.     PAGED_CODE();
    44.     KdPrint(("MyDriver - Entering DriverUnload: DriverObject %8.8lX\n", DriverObject));
    45. }
    46. //-------------------------------------------------------------------------------
    47. NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
    48. {
    49.     PAGED_CODE();
    50.     KdPrint(("MyDriver - Entering AddDevice: DriverObject %8.8lX, pdo %8.8lX\n", DriverObject, pdo));
    51.     NTSTATUS status;
    52.     UNICODE_STRING LinkName, devName;
    53.     // Создание буферов для имен
    54.     RtlInitUnicodeString(&LinkName, L"\\DosDevices\\SK_REMOTE");
    55.     RtlInitUnicodeString(&devName,   L"\\Device\\devSK_REMOTE");
    56.     // Создаем объект MyDriver чтобы перехватывать irp-запросы.
    57.     PDEVICE_OBJECT fido; // Объект фильтра для устройства
    58.     status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &fido);
    59.     if (!NT_SUCCESS(status))
    60.     {                       // Объект устройства не был создан
    61.         KdPrint(("MyDriver - IoCreateDevice failed - %X\n", status));
    62.         return status;
    63.     }              
    64.     // Создание символьного имени драйвера
    65.     status = IoCreateSymbolicLink (&LinkName, &devName);
    66.     if (!NT_SUCCESS(status))return status;
    67.     KdPrint(("MyDriver - Symbolic link"));
    68.    
    69.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    70.     __try
    71.     {
    72.         MyIoInitializeRemoveLock(&pdx->RemoveLock, 0, 0, 255);
    73.         pdx->DeviceObject = fido;
    74.         pdx->Pdo = pdo;
    75.         // Вставляем фильтр драйвер в стек нижележайшего драйвера
    76.         PDEVICE_OBJECT fdo = IoAttachDeviceToDeviceStack(fido, pdo);
    77.         pdx->LowerDeviceObject = fdo;
    78.         fido->Flags |= fdo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH);
    79.         fido->DeviceType = fdo->DeviceType;
    80.         fido->Characteristics = fdo->Characteristics;
    81.         fido->AlignmentRequirement = fdo->AlignmentRequirement;    
    82.         fido->Flags &= ~DO_DEVICE_INITIALIZING;
    83.     }
    84.     __finally
    85.     {                       // В случае сбоя
    86.         if (!NT_SUCCESS(status))
    87.         {                   // Удаляем фильтр
    88.             IoDeleteDevice(fido);
    89.             return status;
    90.         }                  
    91.     }
    92.     return status;
    93. }
    94. //-------------------------------------------------------------------------------
    95. #pragma LOCKEDCODE
    96. NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info)
    97. {
    98.     Irp->IoStatus.Status = status;
    99.     Irp->IoStatus.Information = info;
    100.     IoCompleteRequest(Irp, IO_NO_INCREMENT);
    101.     return status;
    102. }
    103. //-------------------------------------------------------------------------------
    104. #pragma LOCKEDCODE
    105. NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    106. {
    107.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    108.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    109.  
    110.     KdPrint(("MyDriver - DispathAny!!!!"));
    111.     NTSTATUS status;
    112.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    113.     if (!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0);
    114.     IoSkipCurrentIrpStackLocation(Irp);
    115.     status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    116.     MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    117.     return status;
    118. }
    119. //-------------------------------------------------------------------------------
    120. NTSTATUS InternalIOCTLCompletion(IN PDEVICE_OBJECT fido, IN PIRP Irp, IN PVOID Context)
    121. {
    122.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    123.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    124.  
    125.     if(Irp->PendingReturned)IoMarkIrpPending( Irp );
    126.     ULONG uSequenceNumber = (ULONG)Context;
    127.     ULONG dwControlCode = stack->Parameters.DeviceIoControl.IoControlCode;
    128.     if(IOCTL_INTERNAL_USB_SUBMIT_URB == dwControlCode)
    129.     {
    130.         PURB pUrb = (PURB)stack->Parameters.Others.Argument1;
    131.         // Свой обработчик
    132.     }
    133.     return STATUS_SUCCESS;
    134. }
    135. //-------------------------------------------------------------------------------
    136. NTSTATUS DispatchInternalIOCTL(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    137. {
    138.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    139.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    140.     ULONG dwControlCode = stack->Parameters.DeviceIoControl.IoControlCode;
    141.  
    142.     NTSTATUS status;
    143.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    144.     if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0);
    145.  
    146.     if(IOCTL_INTERNAL_USB_SUBMIT_URB == dwControlCode)
    147.     {
    148.         ULONG uSequenceNumber = InterlockedIncrement((PLONG)&pdx->uSequenceNumber);
    149.         IoCopyCurrentIrpStackLocationToNext(Irp);
    150.         IoSetCompletionRoutine(Irp, InternalIOCTLCompletion, (PVOID)uSequenceNumber, TRUE, TRUE, TRUE);
    151.         status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    152.         MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    153.     }
    154.     else
    155.     {
    156.         IoSkipCurrentIrpStackLocation(Irp);
    157.         status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    158.         MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    159.     }
    160.     return status;
    161. }
    162. //-------------------------------------------------------------------------------
    163. NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    164. {
    165.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    166.     PoStartNextPowerIrp(Irp);  
    167.     NTSTATUS status;
    168.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    169.     if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0);
    170.     IoSkipCurrentIrpStackLocation(Irp);
    171.     status = PoCallDriver(pdx->LowerDeviceObject, Irp);
    172.     MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    173.     return status;
    174. }
    175. //-------------------------------------------------------------------------------
    176. NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    177. {
    178.     PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    179.     ULONG fcn = stack->MinorFunction;
    180.    
    181.     NTSTATUS status;
    182.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    183.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    184.     if(!NT_SUCCESS(status))return CompleteRequest(Irp, status, 0);
    185.     IoSkipCurrentIrpStackLocation(Irp);
    186.     status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    187.    
    188.     if(fcn == IRP_MN_REMOVE_DEVICE)
    189.     {
    190.         MyIoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
    191.         RemoveDevice(fido);
    192.     }
    193.     else MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    194.     return status;
    195. }
    196. //-------------------------------------------------------------------------------
    197. NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    198. {   // DispatchWmi
    199.     NTSTATUS status;
    200.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    201.     status = MyIoAcquireRemoveLock(&pdx->RemoveLock, Irp);
    202.     if (!NT_SUCCESS(status)) return CompleteRequest(Irp, status, 0);
    203.     IoSkipCurrentIrpStackLocation(Irp);
    204.     status = IoCallDriver(pdx->LowerDeviceObject, Irp);
    205.     MyIoReleaseRemoveLock(&pdx->RemoveLock, Irp);
    206.     return status;
    207. }
    208. //-------------------------------------------------------------------------------
    209. #pragma PAGEDCODE
    210.  
    211. VOID RemoveDevice(IN PDEVICE_OBJECT fido)
    212. {
    213.     PAGED_CODE();
    214.     UNICODE_STRING LinkName;
    215.     // Создание буферов для имен
    216.     RtlInitUnicodeString(&LinkName, L"\\DosDevices\\SK_REMOTE");
    217.     KdPrint(("Delete symbolic link"));
    218.     IoDeleteSymbolicLink(&LinkName);
    219.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fido->DeviceExtension;
    220.     if(pdx->LowerDeviceObject)IoDetachDevice(pdx->LowerDeviceObject);
    221.     IoDeleteDevice(fido);
    222. }
    223. //-------------------------------------------------------------------------------
    224. #pragma LOCKEDCODE
    225.  
    226. extern "C" void __declspec(naked) __cdecl _chkesp()
    227. {
    228.     _asm je okay
    229.     ASSERT(!"Stack pointer mismatch!");
    230. okay:
    231.     _asm ret
    232. }
    файл Driver.h
    Код (Text):
    1. #ifndef _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_
    2. #define _DRIVER_H_04802_BASHBD_1UIWQ1_8239_1NJKDH832_901_
    3.  
    4. #ifdef __cplusplus
    5. extern "C"
    6. {
    7. #endif
    8.     #include "wdm.h"
    9. #ifdef __cplusplus
    10. }
    11. #endif
    12. ///////////////////////////////////////////////////////////////////////////////
    13. #define PAGEDCODE code_seg("page")
    14. #define LOCKEDCODE code_seg()
    15. #define INITCODE code_seg("init")
    16. //-------------------------------------------------------------------------------
    17. #define PAGEDDATA data_seg("page")
    18. #define LOCKEDDATA data_seg()
    19. #define INITDATA data_seg("init")
    20. //-------------------------------------------------------------------------------
    21. #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
    22. //-------------------------------------------------------------------------------
    23. #if DBG && defined(_X86_)
    24. #undef ASSERT
    25. #define ASSERT(e) if(!(e)){DbgPrint("Assertion failure in "\
    26.     __FILE__ ", line %d: " #e "\n", __LINE__);\
    27.     _asm int 1\
    28. }
    29. #endif
    30. ///////////////////////////////////////////////////////////////////////////////
    31. typedef struct _MY_IO_REMOVE_LOCK {
    32.     LONG usage;                 // reference count
    33.     BOOLEAN removing;           // true if removal is pending
    34.     KEVENT evRemove;            // event to wait on
    35. } MY_IO_REMOVE_LOCK, *PMY_IO_REMOVE_LOCK;
    36.  
    37. VOID MyIoInitializeRemoveLock(PMY_IO_REMOVE_LOCK lock, ULONG tag, ULONG minutes, ULONG maxcount);
    38. NTSTATUS MyIoAcquireRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag);
    39. VOID MyIoReleaseRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag);
    40. VOID MyIoReleaseRemoveLockAndWait(PMY_IO_REMOVE_LOCK lock, PVOID tag);
    41. ///////////////////////////////////////////////////////////////////////////////
    42. // Device extension structure
    43.  
    44. typedef struct tagDEVICE_EXTENSION {
    45.     PDEVICE_OBJECT DeviceObject;            // device object this extension belongs to
    46.     PDEVICE_OBJECT LowerDeviceObject;       // next lower driver in same stack
    47.     PDEVICE_OBJECT Pdo;                     // the PDO
    48.     MY_IO_REMOVE_LOCK RemoveLock;
    49.     ULONG          uSequenceNumber;
    50. }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
    51.  
    52. ///////////////////////////////////////////////////////////////////////////////
    53. // Global functions
    54.  
    55. VOID RemoveDevice(IN PDEVICE_OBJECT fdo);
    56. NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info);
    57.  
    58. extern BOOLEAN win98;
    59. extern UNICODE_STRING servkey;
    60. extern UCHAR CODE[32];
    61. extern ULONG nBytesRead;
    62.  
    63. #endif // DRIVER_H
    файл RemoveLock.cpp
    Код (Text):
    1. #include "Driver.h"
    2. //-------------------------------------------------------------------------------
    3. #pragma PAGEDCODE
    4.  
    5. VOID MyIoInitializeRemoveLock(PMY_IO_REMOVE_LOCK lock, ULONG tag, ULONG minutes, ULONG maxcount)
    6. {
    7.     PAGED_CODE();
    8.     KeInitializeEvent(&lock->evRemove, NotificationEvent, FALSE);
    9.     lock->usage = 1;
    10.     lock->removing = FALSE;
    11. }
    12. //-------------------------------------------------------------------------------
    13. #pragma LOCKEDCODE
    14.  
    15. NTSTATUS MyIoAcquireRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag)
    16. {
    17.     LONG usage = InterlockedIncrement(&lock->usage);
    18.     if (lock->removing)
    19.     {                       // removal in progress
    20.         if (InterlockedDecrement(&lock->usage) == 0)
    21.             KeSetEvent(&lock->evRemove, 0, FALSE);
    22.         return STATUS_DELETE_PENDING;
    23.     }                       // removal in progress
    24.     return STATUS_SUCCESS;
    25. }
    26. //-------------------------------------------------------------------------------
    27. VOID MyIoReleaseRemoveLock(PMY_IO_REMOVE_LOCK lock, PVOID tag)
    28. {
    29.     if (InterlockedDecrement(&lock->usage) == 0)
    30.         KeSetEvent(&lock->evRemove, 0, FALSE);
    31. }
    32. //-------------------------------------------------------------------------------
    33. #pragma PAGEDCODE
    34.  
    35. VOID MyIoReleaseRemoveLockAndWait(PMY_IO_REMOVE_LOCK lock, PVOID tag)
    36. {
    37.     PAGED_CODE();
    38.     lock->removing = TRUE;
    39.     MyIoReleaseRemoveLock(lock, tag);
    40.     MyIoReleaseRemoveLock(lock, NULL);
    41.     KeWaitForSingleObject(&lock->evRemove, Executive, KernelMode, FALSE, NULL);
    42. }
    43. //-------------------------------------------------------------------------------
    Файл sources
    Код (Text):
    1. TARGETNAME=UsbSnoop
    2.  
    3. TARGETPATH=obj
    4. TARGETTYPE=DRIVER
    5.  
    6. SOURCES= DriverEntry.cpp \
    7.          RemoveLock.cpp
    Файл makefile содержит только строку: !INCLUDE $(NTMAKEENV)\makefile.def
     
  8. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    RedField
    Где-то уже создавали подобную тему. Отсылаю вас к чтению документации по драйверам фильтрам. Потому что некоторые драйверы не позволяют открывать, либо использовать его как нужно манипулятор. Да и вообще есть корректный официальный способ работы с фильтрами. Необходимо создать объект Extra Device Object. Он будет скрывать объект FiDO в стеке PnP. И в функции AddDevice создаются два объекта устройства FiDO который собственно и подключается к стеку PnP, и объект EDO с уникальным именем, но него не подключают к PnP. Ну и символическая ссылка на EDO тоже создается. Вроде уже приводил этот псевдокод.

    Код (Text):
    1. typedef struct _COMMON_DEVICE_EXTENSION {
    2.   ULONG flag;
    3. } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
    4.  
    5. typedef struct _DEVICE_EXTENSION : public _COMMON_DEVICE_EXTENSION {
    6.  
    7.   struct _EXTRA_DEVICE_EXTENSION* edx;
    8.  
    9. } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
    10.  
    11. typedef struct _EXTRA_DEVICE_EXTENSION : public  _COMMON_DEVICE_EXTENSION {
    12.  
    13.   PDEVICE_EXTENSION pdx;
    14.  
    15. } EXTRA_DEVICE_EXTENSION, *PEXTRA_DEVICE_EXTENSION;
    16.  
    17. #define FIDO_EXTENSION 0
    18. #define EDO_EXTENSION 1
    19.  
    20. ........
    21. NTSTATUS AddDevice(PDRIVER_OBJECT Driver Object, PDEVICE_OBJECT pdo)
    22. {
    23.   PDEVICE_OBJECT fido;
    24.   IoCreateDevice(...);
    25.   PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    26.  
    27.   //other staff
    28.  
    29.   pdx->flag = FIDO_EXTENSION;
    30.  
    31.   WCHAR namebuf[64];
    32.   static LONG numextra = -1;
    33.   _snwprintf(namebuf, arraysize(namebuf), L"\\Device\\MyExtra%d",   InterlockedIncrement(&numextra));
    34.   UNICODE_STRING edoname;
    35.   RtlInitUnicodeString(&ednoname, namebuf);
    36.   IoCreateDevice(DriverObject, sizeof(EXTRA_DEVICE_EXTENSION), &edoname, FILE_DEVICE_UNKNOWN, 0, FALSE, &edo);
    37.  
    38.   PEXTRA_DEVICE_EXTENSION edx =  (PEXTRA_DEVICE_EXTENSION) edo->DeviceExtension;
    39.   edx->flag = EDO_EXTENSION;
    40.   edx->pdx = pdx;
    41.   pdx->edx = edx;
    42. }
    В диспетчерской функции указатель на DeviceExtention объекта устройства вначале преобразуется в PCOMMON_DEVICE_EXTENTION, а затем по содержимому поля флагов определяете, к какому объекту предназначен IRP = к FiDO или EDO. Ну и как определили что запрос по EDO - делаете свои действия.

    Ну и вот и вся хитрость. Все это описано у Walter Oney.
     
  9. RedField

    RedField New Member

    Публикаций:
    0
    Регистрация:
    28 май 2010
    Сообщения:
    8
    TermoSINteZ
    Спасибо за помощь. Буду пробовать.
     
  10. JhanGhuangxi

    JhanGhuangxi New Member

    Публикаций:
    0
    Регистрация:
    15 апр 2010
    Сообщения:
    31
    RedField
    В качестве замечания к коду:
    В функции функции DispatchAny сделай проверку, какому DEVICE_OBJECT ты пропускаешь IRP, а то получается, что любые IPR, проходящие через твой фильтр ты пересылаешь через IoCallDriver, тогда как IRP, адресованные именно твоему фильтру можно заканчивать вызовом CompleteRequest.
    Примерно так:
    Код (Text):
    1. NTSTATUS
    2. FilterDispatchIo(
    3.     IN PDEVICE_OBJECT    DeviceObject,
    4.     IN PIRP              Irp
    5.     )
    6. /*++
    7.  
    8. Routine Description:
    9.  
    10.     This routine is the dispatch routine for non passthru irps.
    11.     We will check the input device object to see if the request
    12.     is meant for the control device object. If it is, we will
    13.     handle and complete the IRP, if not, we will pass it down to
    14.     the lower driver.
    15.    
    16. Arguments:
    17.  
    18.     DeviceObject - Pointer to the device object.
    19.  
    20.     Irp - Pointer to the request packet.
    21.  
    22. Return Value:
    23.  
    24.     NT Status code
    25. --*/
    26. {
    27.     PIO_STACK_LOCATION  irpStack;
    28.     NTSTATUS            status;
    29.  
    30.     PAGED_CODE();
    31.  
    32.     //
    33.     // Please note that this is a common dispatch point for controlobject and
    34.     // filter deviceobject attached to the pnp stack.
    35.     //
    36.     if(DeviceObject != ControlDeviceObject)
    37.     {
    38.          
    39.         // We will just  the request down as we are not interested in handling
    40.         // requests that come on the PnP stack.
    41.          
    42.         return FilterPass(DeviceObject, Irp);    
    43.     }
    44.    
    45.     //
    46.     // Else this is targeted at our control deviceobject so let's handle it.
    47.     // Here we will handle the IOCTl requests that come from the app.
    48.     //    
    49.     status = STATUS_SUCCESS;
    50.     Irp->IoStatus.Information = 0;
    51.     irpStack = IoGetCurrentIrpStackLocation (Irp);
    52.  
    53.     switch (irpStack->MajorFunction) {
    54.         case IRP_MJ_CREATE:
    55.             DebugPrint(("Create \n"));
    56.             break;
    57.            
    58.         case IRP_MJ_CLOSE:
    59.             DebugPrint(("Close \n"));
    60.             break;
    61.            
    62.         case IRP_MJ_CLEANUP:
    63.             DebugPrint(("Cleanup \n"));
    64.             break;
    65.            
    66.          case  IRP_MJ_DEVICE_CONTROL:
    67.             DebugPrint(("DeviceIoControl\n"));
    68.             switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
    69.                 //
    70.                 //case IOCTL_CUSTOM_CODE:
    71.                 //
    72.                 default:
    73.                     status = STATUS_INVALID_PARAMETER;
    74.                     break;
    75.             }
    76.         default:
    77.             break;
    78.     }
    79.  
    80.     Irp->IoStatus.Status = status;
    81.     IoCompleteRequest (Irp, IO_NO_INCREMENT);
    82.     return status;
    83. }
     
  11. JhanGhuangxi

    JhanGhuangxi New Member

    Публикаций:
    0
    Регистрация:
    15 апр 2010
    Сообщения:
    31
    В функция FilterPass, если IRP тебе не предназначен, ты просто отправляешь IRP дальше по стеку
     
  12. RedField

    RedField New Member

    Публикаций:
    0
    Регистрация:
    28 май 2010
    Сообщения:
    8
    Получилось!

    Содержимое файла Driver.h
    Код (Text):
    1. ///////////////////////////////////////////////////////////////////////////////
    2. // Device extension structure
    3. typedef struct _COMMON_DEVICE_EXTENSION{
    4.     ULONG flag;
    5. }COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
    6.  
    7. typedef struct _DEVICE_EXTENSION: public _COMMON_DEVICE_EXTENSION {
    8.     struct _EXTRA_DEVICE_EXTENSION* edx;
    9.     PDEVICE_OBJECT DeviceObject;           
    10.     PDEVICE_OBJECT LowerDeviceObject;       // next lower driver in same stack
    11.     PDEVICE_OBJECT Pdo;                     // the PDO
    12.     MY_IO_REMOVE_LOCK RemoveLock;
    13.     ULONG          uSequenceNumber;
    14. }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
    15.  
    16. typedef struct _EXTRA_DEVICE_EXTENSION: public _COMMON_DEVICE_EXTENSION{
    17.     PDEVICE_OBJECT DeviceObject;
    18.     PDEVICE_EXTENSION pdx;
    19. }EXTRA_DEVICE_EXTENSION, *PEXTRA_DEVICE_EXTENSION;
    20.  
    21. #define FIDO_EXTENSION 0
    22. #define EDO_EXTENSION 1
    Структура _COMMON_DEVICE_EXTENSION нужна, чтобы в структурах расширения обоих устройств было общее поле flag по которому можно определить к какому объекту устройства принадлежит пакет IRP . Если flag == FIDO_EXTENSION, то посылаем IRP ниже по стеку, а если flag == EDO_EXTENSION - то IRP адресован нам.

    Создание объектов устройств (проверку на ошибки я опустил):
    Код (Text):
    1. PDEVICE_OBJECT fido; // Объект фильтра для устройства
    2. PDEVICE_OBJECT edo;  // Именнованный объект устройства
    3. status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &fido);
    4. PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    5. pdx->flag = FIDO_EXTENSION;
    6. ...
    7. status = IoCreateDevice(DriverObject, sizeof(EXTRA_DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &edo);
    8. PEXTRA_DEVICE_EXTENSION edx = (PEXTRA_DEVICE_EXTENSION) edo->DeviceExtension;
    9. edx->flag = EDO_EXTENSION;
    10. ...
    11.     // Создание символьного имени драйвера
    12.     status = IoCreateSymbolicLink (&LinkName, &devName);
    Теперь как определить кому адресован IRP!!!
    В DispatchAny обрабатываются IRP_MJ_READ/IRP_MJ_CREATE/IRP_MJ_CLOSE и др.
    Чтобы узнать к какому объекту устройства адресован IRP - пакет, нужно явно привести указатель на структуру расширения устройства к одному из типов: PDEVICE_EXTENSION или PEXTRA_DEVICE_EXTENSION и затем по полю flag определить кому адресован IRP.
    Пример:
    Код (Text):
    1. NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    2. {
    3.     PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
    4.     if(pdx->flag==FIDO_EXTENSION)
    5.     {
    6.           // Пакет адресован фильтр-драйверу. Тут мы можем зарегистрировать свою
    7.           // процедуру завершения и обязательно передать IRP - пакет ниже по стеку.
    8.           ...
    9.     }
    10.     else
    11.     {
    12.           // Пакет адресован нам, т.е. в моем случае он был послан из оконного приложения
    13.           ...
    14.     }
    15. }
    При этом получается, что если пакет послан объекту утройства 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):
    1. PDEVICE *pp;
    2. ...
    3. pp = fido;
    4. ...
    5. NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp)
    6. {
    7.    if(pp == fido)
    8.    {
    9.     // адресован fido
    10.    }
    11.    else
    12.    {
    13.    // адресован нам
    14.    }
    15. }