Не проходят IRP_MJ_READ пакеты. В чем дело?

Тема в разделе "WASM.NT.KERNEL", создана пользователем serg128, 12 авг 2009.

  1. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Привет всем!
    Пишу фильтр клавиатуры, успешно прицепился к стеку(виден в DeviceTree):
    Код (Text):
    1.     PDEVICE_EXTENSION     devExt;
    2.     PDEVICE_OBJECT           device;
    3.     UNICODE_STRING          devName;
    4.     NTSTATUS                      status;
    5.  
    6.     status = IoCreateDevice(DriverObject,
    7.                             sizeof(DEVICE_EXTENSION),
    8.                             NULL,
    9.                             FILE_DEVICE_KEYBOARD,
    10.                             0,
    11.                             FALSE,
    12.                             &device
    13.                             );
    14.  
    15.     if (!NT_SUCCESS(status)) {
    16.         return (status);
    17.     }
    18.  
    19.     RtlZeroMemory(device->DeviceExtension, sizeof(DEVICE_EXTENSION));
    20.     devExt = (PDEVICE_EXTENSION) device->DeviceExtension;
    21.     devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, device);
    22.     RtlInitUnicodeString(&devName, L"\\Device\\KeyboardClass0");
    23.     IoAttachDevice(device, &devName, &devExt->TopOfStack);
    24.  
    25.     if (devExt->TopOfStack == NULL) {
    26.         IoDeleteDevice(device);
    27.         return STATUS_DEVICE_NOT_CONNECTED;
    28.     }
    29.  
    30.     ASSERT(devExt->TopOfStack);
    31.     device->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);
    32.     device->Flags &= ~DO_DEVICE_INITIALIZING;
    33.     return status;
    А вот обработчик DriverObject->MajorFunction [IRP_MJ_READ] = DispatchRead:
    Код (Text):
    1. NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
    2. {
    3.     DbgPrint("Bla Bla");
    4.     IoCopyCurrentIrpStackLocationToNext(pIrp);
    5.     return IoCallDriver(((PDEVICE_EXTENSION)pDeviceObject->DeviceExtension)->pKeyboardDevice, pIrp);
    6. }
    Т.е. в моем понимании, при нажатии клавиш, должна вызываться ф-ция DispatchRead.
    Но сообщения в DriverMonitor я не вижу. Где моя ошибка?
     
  2. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Когда же вы наконец поймёте, что когда что-то пишешь нельзя тупо копипастить, нужно хотя бы приблизительно понять чужой кусок кода. Вот и здесь явно видно что либо тупо скопипастил, либо писал сам, при этом даже не делая попыток разобраться в происходящем. Итого:

    Посмотри внимательно документацию на функцию IoAttachDeviceToDeviceStack(), думаю, это наведёт тебя на мысль о природе твоей ошибки. Кроме того, на сегодняшний день рекомендуется использовать вместо неё IoAttachDeviceToDeviceStackSafe().

    А это ничего, что значение полю pKeyboardDevice нигде не присваивается?
     
  3. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Каюсь, грешен, но с этими драйверами черт ногу сломит...
    Но: 1. К стеку мы всетаки прицепились (а про ф-цию сейчас прочитаю-исправлю(сь)) :)
    2. этих вызовов может и не быть в DispatchRead, но както управление туда ведь должно попадать?
     
  4. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Так, ещё раз.

    1. Зачем здесь вообще вызов IoAttachDeviceToDeviceStack()? Это совершенно лишнее, убери.

    2. Создание фильтрующего устройства не совсем корректно у тебя, ибо

    2.1. Вместо FILE_DEVICE_KEYBOARD следует указать pTargetDevice -> DeviceType.
    2.2. Вместо (DO_BUFFERED_IO | DO_POWER_PAGABLE) следует указать pTargetDevice -> Flags (выборочно).

    При этом pTargetDevice следует получить заранее через IoGetDeviceObjectPointer() и использовать IoAttachDeviceToDeviceStackSafe() вместо IoAttachDevice(). Именно так, потому что в общем случае ты не знаешь характеристик целевого девайса, а это важно, т.к. твой девайс должен иметь те же параметры.

    3. Это верно:

    4. Поле pKeyboardDevice тебе не нужно, замени на TopOfStack.

    5. Что с остальными запросами? Например, ты IRP_MJ_CREATE обрабатываешь? Или только IRP_MJ_READ? Приложения-то как там вообще, с ума не сходят после загрузки твоего фильтра?

    6. Как насчёт обработки IRP_MJ_PNP и IRP_MJ_POWER? Они вообще-то обязательны.

    Ты вообще legacy или WDM фильтр хочешь? Я посоветовал бы взять пример kbfiltr из WDK, там всё как надо, но это WDM, если что.
     
  5. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    По первому пункту исправился:
    Код (Text):
    1.     PDEVICE_EXTENSION        devExt;
    2.     PDEVICE_OBJECT           device;
    3.     UNICODE_STRING           devName;
    4.     NTSTATUS                 status;
    5.     PFILE_OBJECT             use_fileObject;
    6.     PDEVICE_OBJECT           use_deviceObject;
    7.  
    8.     status = IoCreateDevice(DriverObject,
    9.                             sizeof(DEVICE_EXTENSION),
    10.                             NULL,
    11.                             FILE_DEVICE_KEYBOARD,
    12.                             0,
    13.                             FALSE,
    14.                             &device
    15.                             );
    16.  
    17.     if (!NT_SUCCESS(status)) {
    18.         return (status);
    19.     }
    20.  
    21.     RtlZeroMemory(device->DeviceExtension, sizeof(DEVICE_EXTENSION));
    22.     devExt = (PDEVICE_EXTENSION) device->DeviceExtension;
    23.     RtlInitUnicodeString(&devName, L"\\Device\\KeyboardClass0");
    24.  
    25.     status = IoGetDeviceObjectPointer(&devName, FILE_READ_DATA, &use_fileObject, &use_deviceObject);
    26.     if(!NT_SUCCESS(status))
    27.     {
    28.         DbgPrint("Error get device object poiner: %d", status);
    29.         return status;
    30.     }
    31.     devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, use_deviceObject);
    32.  
    33.     if (devExt->TopOfStack == NULL) {
    34.         IoDeleteDevice(device);
    35.         return STATUS_DEVICE_NOT_CONNECTED;
    36.     }
    37.  
    38.     ASSERT(devExt->TopOfStack);
    39.     device->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);
    40.     device->Flags &= ~DO_DEVICE_INITIALIZING;
    41.     return status;
    Обработчик IRP_MJ_READ сделал пустым(только DbgPrint), но туда не заходит управление.
     
  6. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    По первому пункту исправился:
    Код (Text):
    1.     PDEVICE_EXTENSION        devExt;
    2.     PDEVICE_OBJECT           device;
    3.     UNICODE_STRING           devName;
    4.     NTSTATUS                 status;
    5.     PFILE_OBJECT             use_fileObject;
    6.     PDEVICE_OBJECT           use_deviceObject;
    7.  
    8.     status = IoCreateDevice(DriverObject,
    9.                             sizeof(DEVICE_EXTENSION),
    10.                             NULL,
    11.                             FILE_DEVICE_KEYBOARD,
    12.                             0,
    13.                             FALSE,
    14.                             &device
    15.                             );
    16.  
    17.     if (!NT_SUCCESS(status)) {
    18.         return (status);
    19.     }
    20.  
    21.     RtlZeroMemory(device->DeviceExtension, sizeof(DEVICE_EXTENSION));
    22.     devExt = (PDEVICE_EXTENSION) device->DeviceExtension;
    23.     RtlInitUnicodeString(&devName, L"\\Device\\KeyboardClass0");
    24.  
    25.     status = IoGetDeviceObjectPointer(&devName, FILE_READ_DATA, &use_fileObject, &use_deviceObject);
    26.     if(!NT_SUCCESS(status))
    27.     {
    28.         DbgPrint("Error get device object poiner: %d", status);
    29.         return status;
    30.     }
    31.     devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, use_deviceObject);
    32.  
    33.     if (devExt->TopOfStack == NULL) {
    34.         IoDeleteDevice(device);
    35.         return STATUS_DEVICE_NOT_CONNECTED;
    36.     }
    37.  
    38.     ASSERT(devExt->TopOfStack);
    39.     device->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);
    40.     device->Flags &= ~DO_DEVICE_INITIALIZING;
    41.     return status;
    Обработчик IRP_MJ_READ сделал пустым(только DbgPrint), но туда не заходит управление.
     
  7. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Упс, не то хотел отправить, вот окончательный код, с учетом всех исправлений:
    Код (Text):
    1.     PDEVICE_EXTENSION  devExt;
    2.     PDEVICE_OBJECT        device;
    3.     UNICODE_STRING       devName;
    4.     NTSTATUS                  status;
    5.     PFILE_OBJECT            use_fileObject;
    6.     PDEVICE_OBJECT       use_deviceObject;
    7.  
    8.     RtlInitUnicodeString(&devName, L"\\Device\\KeyboardClass0");
    9.     status = IoGetDeviceObjectPointer(&devName, FILE_READ_DATA, &use_fileObject, &use_deviceObject);
    10.     if(!NT_SUCCESS(status))
    11.     {
    12.         DbgPrint("Error get device object poiner: %d", status);
    13.         return status;
    14.     }
    15.  
    16.     status = IoCreateDevice(DriverObject,
    17.                             sizeof(DEVICE_EXTENSION),
    18.                             NULL,
    19.                             use_deviceObject->DeviceType,
    20.                             0,
    21.                             FALSE,
    22.                             &device
    23.                             );
    24.  
    25.     if (!NT_SUCCESS(status))
    26.     {
    27.         DbgPrint("Error during device creation: %d", status);
    28.         return (status);
    29.     }
    30.  
    31.     RtlZeroMemory(device->DeviceExtension, sizeof(DEVICE_EXTENSION));
    32.     devExt = (PDEVICE_EXTENSION) device->DeviceExtension;
    33.     devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, use_deviceObject);
    34.  
    35.     if (devExt->TopOfStack == NULL)
    36.     {
    37.         DbgPrint("Impossible to attach device to stack drivers");
    38.         IoDeleteDevice(device);
    39.         return STATUS_DEVICE_NOT_CONNECTED;
    40.     }
    41.  
    42.     ASSERT(devExt->TopOfStack);
    43.     device->Flags = use_deviceObject->Flags;
    44.     device->Flags &= ~DO_DEVICE_INITIALIZING;
    45.     return status;
    А вот с ф-цией IoAttachDeviceToDeviceStackSafe() незадача, нет ее у меня походу:
    Обработчик IRP_MJ_READ до сих пор не работает! В чем еще дело?
     
  8. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    А, все!
    Прицепил клавиатуру PS/2 и все заработало!
    Интересно, а в какой стек цеплять драйвер, если клавиатура работает по bluetooth?
     
  9. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    \Device\KeyboardClass1
     
  10. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    А вот и нифига!
    Вызов IoGetDeviceObjectPointer(); проходит неуспешно. Аналогичную ситуацию описывал автор в 16й статье по разработке драйверов (на этом сайте).
    Здесь походу нужен совсем другой подход... хех...
     
  11. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Ещё раз: цепляться тебе в любом случае к драйверу класса, ибо это есть абстракция от тех самых стеков, о которых ты говоришь. А получить указатель на девайс клавиатуры можно двумя способами:

    1. Написать WDM-фильтр (см. пример в WDK), в этом случае указатель на целевой девайс сам приедет тебе в функцию AddDevice().
    2. В случае legacy-фильтра попробовать получить указатель на объект-девайс топорным методом через IoCreateFileSpecifyDeviceObjectHint() с соответствующими флагами.

    Не советую использовать для этого ObReferenceObjectByName(), потому как для объектов типа "Device" эта функция не работает.
     
  12. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    Спасибо за совет, попробую обязательно. Но для начала доведу до ума начатое:
    сейчас споткнулся на получении сканкодов клавиш, т.е.:
    Код (Text):
    1. NTSTATUS DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
    2. {
    3.     PKEYBOARD_INPUT_DATA     KeyData;
    4.     KeyData = Irp->AssociatedIrp.SystemBuffer;
    5.     DbgPrint("Key pressed: %d", KeyData[0].MakeCode);
    6.  
    7.     IoCopyCurrentIrpStackLocationToNext(Irp);
    8.     return IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->TopOfStack, Irp);
    9. }
    Выводит постоянно 0. А по описанию это должен быть сканкод.
     
  13. serg128

    serg128 New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    55
    >x64
    Насчет присоединиться к стеку другой клавиатуры(не ps/2): так ведь в AddDevice по сути будет тот же самый код, что сейчас у меня отвечает за соединение со стеком. В чем принципиальное отличие WDM?
     
  14. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    А ты почитай в документации про

    1. регистрацию WDM-драйверов.
    2. функцию AddDevice, её назначение и использование.

    Мне, честно говоря, уже лень объяснять такую элементарщину...
     
  15. Riply

    Riply New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2007
    Сообщения:
    25
    Адрес:
    Petersburg
    x64
    2. В случае legacy-фильтра попробовать получить указатель на объект-девайс топорным методом через IoCreateFileSpecifyDeviceObjectHint() с соответствующими флагами.

    Было несколько попыток, типа:
    Код (Text):
    1. if (pModInitParams->InitParam.LowPart == 0)
    2.                               RtlInitUnicodeString(&KbdDevClassName, L"\\Device\\KeyboardClass0");
    3.                             else RtlInitUnicodeString(&KbdDevClassName, L"\\Device\\KeyboardClass1");
    4.  
    5.                             InitializeObjectAttributesKrnlObj(&ObjAttr, &KbdDevClassName, OBJ_CASE_INSENSITIVE, NULL, NULL);
    6.                             RetStatus = IoCreateFileSpecifyDeviceObjectHint(&KbdHandle,
    7.                                                                             FILE_READ_ATTRIBUTES,
    8.                                                                             &ObjAttr,
    9.                                                                             &IoBlock,
    10.                                                                             NULL,
    11.                                                                             FILE_ATTRIBUTE_DEVICE,
    12.                                                                             FILE_SHARE_READ | FILE_SHARE_WRITE,
    13.                                                                             FILE_OPEN ,
    14.                                                                             FILE_NON_DIRECTORY_FILE | IO_ATTACH_DEVICE_API,
    15.                                                                             NULL,
    16.                                                                             0,
    17.                                                                             CreateFileTypeNone,
    18.                                                                             NULL,
    19.                                                                             IO_IGNORE_SHARE_ACCESS_CHECK,
    20.                                                                             NULL);
    21.                             Log_WriteW(L"DriverEntry", L"IoCreateFileSpecifyDeviceObjectHint", RetStatus);
    22.  
    23.                             if NT_SUCCESS( RetStatus )
    24.                               __try
    25.                                 {
    26.                                   PFILE_OBJECT LocalFileObject;
    27.                                   RetStatus = ObReferenceObjectByHandle(KbdHandle, 0, *IoFileObjectType, KernelMode, (PVOID*)&LocalFileObject, NULL);
    28.                                   Log_WriteW(L"DriverEntry", L"ObReferenceObjectByHandle", RetStatus);
    29.                                   if (NT_SUCCESS(RetStatus))
    30.                                     __try
    31.                                       {
    32.                                         PDEVICE_OBJECT TargetDevice = IoGetRelatedDeviceObject(LocalFileObject);
    33.                                         if (TargetDevice)
    34.                                           RetStatus = IoAttachDeviceToDeviceStackSafe(deviceObject, TargetDevice, &extension->DeviceObject);
    35.                                         else RetStatus = STATUS_ACCESS_VIOLATION;
    36.                                       }
    37.                                     __finally
    38.                                       {
    39.                                         ObDereferenceObject(LocalFileObject);
    40.                                       }
    41.  
    42.                                 }
    43.                               __finally
    44.                                 {
    45.                                   ZwClose(KbdHandle);
    46.                                 };
    но к успеху они не привели: возвращаемая ошибка "файл занят другим приложением".
    Это было только предположение, или реально получилось ?
    Если второе, то не подскажите ли где я партачу ?

    P.S.
    C KeyboardClass0 все работает.