Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Один fdo подключенный к нескольким драйверам ?  (Прочитано 12731 раз)
0 Пользователей и 1 Гость смотрят эту тему.
falcon
Гость
« : 03-02-2004 14:35 » 

А можно ли один FDO подключить к нескольким драйверам?
Иными словами, теоретически я могу сделать IoAttachDevice, например, два раза, подключив свой фдо к нескольким драйверам, тогда в мой обработчик ИРП будут попадать ИРПшки от обоих драйверов, к которым я подключился. Можно ли как-либо определить, чей ИРП пришел в мой обработчик?

А то нехочется грузить два своих драйвера для, в общем-то, одной и той же цели...
Записан
Maaaaaaaaad
Гость
« Ответ #1 : 03-02-2004 16:59 » 

Цитата

Можно ли как-либо определить, чей ИРП пришел в мой обработчик

Вроде   Вот такой я вот через стек локейшн можно определять указатель на девайс обжект
Записан
falcon
Гость
« Ответ #2 : 03-02-2004 17:38 » 

Цитата: Maaaaaaaaad

Можно ли как-либо определить, чей ИРП пришел в мой обработчик

Вроде   Вот такой я вот через стек локейшн можно определять указатель на девайс обжект


А примерчик можно ?
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #3 : 04-02-2004 06:11 » 

Цитата

А можно ли один FDO подключить к нескольким драйверам?
Иными словами, теоретически я могу сделать IoAttachDevice, например, два раза, подключив свой фдо к нескольким драйверам, тогда в мой обработчик ИРП будут попадать ИРПшки от обоих драйверов, к которым я подключился. Можно ли как-либо определить, чей ИРП пришел в мой обработчик?

А то нехочется грузить два своих драйвера для, в общем-то, одной и той же цели...


Тут у тебя обычная путаница между DEVICE_OBJECT и DRIVER_OBJECT. Значит так- FDO не подключают к драйверам(DRIVER_OBJECT), его подключают к  DEVICE_OBJECT. Подключить один FDO можно к разным DEVICE_OBJECT.

Цитата

А то нехочется грузить два своих драйвера для, в общем-то, одной и той же цели...


Тебе и не дадут два драйвера загрузить. А вот сделать два DEVICE_OBJECT из одого драйвера можно.

Цитата

Можно ли как-либо определить, чей ИРП пришел в мой обработчик?


Конечно можно, только не через Stack Location- нижний еще не заполнен, есть верхний, но он скорее всего тебе ничего не даст. Определяй какими нибудь другими способами. Но сделать два FDO на порядок проще.

Указатель на верхний DEVICE_OBJECT находится в DEVICE_OBJECT.AttachedDevice , указатель на нижний ты сам получаешь и обычно хранят в DEVICE_OBJECT.DeviceExtension .
Записан
Anonymous
Гость
« Ответ #4 : 04-02-2004 08:42 » 

Цитата: SlavaI

А можно ли один FDO подключить к нескольким драйверам?
[...]
Тут у тебя обычная путаница между DEVICE_OBJECT и DRIVER_OBJECT. Значит так- FDO не подключают к драйверам(DRIVER_OBJECT), его подключают к  DEVICE_OBJECT. Подключить один FDO можно к разным DEVICE_OBJECT.

Тебе и не дадут два драйвера загрузить. А вот сделать два DEVICE_OBJECT из одого драйвера можно.


Попытался сделать так, как ты говоришь, теперь НТюк валится в синий экран при попытке загрузить драйвер. Посмотри, пожалуйста, что я делаю не так?
Код:

#include <ntddk.h>
#include "NemesisDrv.h"
#include <parallel.h>
#include <ntddkbd.h>

#define K_CLASS0        L"\\Device\\KeyboardClass0"
#define M_CLASS0        L"\\Device\\MouseClass0"

typedef struct _DEVICE_EXTENSION |
  PDRIVER_OBJECT  DriverObject;
  PDEVICE_OBJECT  Dev;
  PDEVICE_OBJECT  TopOfStack;
" DEVICE_EXTENSION, *PDEVICE_EXTENSION;

static  UNICODE_STRING  USName, USLink;

NTSTATUS DriverEntry)IN PDRIVER_OBJECT DriverObject,
                                              IN PUNICODE_STRING RegistryPath: |
  PDEVICE_OBJECT    deviceObjectK, deviceObjectM;
  PDEVICE_EXTENSION extK, extM;
  UNICODE_STRING    USStrK, USStrM;
  NTSTATUS          ntStatus;
  LONG              i;

  for)i=0; i<IRP_MJ_MAXIMUM_FUNCTION; i++: |
    DriverObject->MajorFunction[i(=PassThrough;
  "
  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL(=DriverDeviceControl;
  DriverObject->DriverUnload=DriverUnload;
  DriverObject->MajorFunction[IRP_MJ_CREATE(=DriverOpen;
  DriverObject->MajorFunction[IRP_MJ_CLOSE(=DriverClose;
  DriverObject->MajorFunction[IRP_MJ_READ(=ReadDispatchK;
  RtlInitUnicodeString)&USName, NT_DEVICE_NAME:;
  ntStatus=IoCreateDevice)DriverObject, sizeof)DEVICE_EXTENSION:,
                          &USName, FILE_DEVICE_KEYBOARD, 0,
                          FALSE, &deviceObjectK:;
  if )!NT_SUCCESS)ntStatus:: |
    RtlFreeUnicodeString)&USName:; return ntStatus;
  "
  extK=)PDEVICE_EXTENSION: deviceObjectK->DeviceExtension;
  RtlZeroMemory)extK, sizeof)DEVICE_EXTENSION::;
  extK->DriverObject=DriverObject; extK->Dev=deviceObjectK;

  RtlInitUnicodeString)&USLink, DOS_DEVICE_NAME:;

  ntStatus=IoCreateSymbolicLink)&USLink, &USName:;
  if )ntStatus!=STATUS_SUCCESS: |
    RtlFreeUnicodeString)&USLink:; RtlFreeUnicodeString)&USName:;
    IoDeleteDevice)deviceObjectK:; return ntStatus;
  "
  deviceObjectK->Flags|=)DO_BUFFERED_IO|DO_POWER_PAGABLE:;
  RtlInitUnicodeString)&USStrK, K_CLASS0:;
  // Attach to the keyboard chain.
  ntStatus=IoAttachDevice)deviceObjectK, &USStrK, &extK->TopOfStack:;
  if )ntStatus!=STATUS_SUCCESS: |
    IoDeleteSymbolicLink)&USLink:; IoDeleteDevice)deviceObjectK:;
    return ntStatus;
  "
  for)i=0; i<IRP_MJ_MAXIMUM_FUNCTION; i++: |
    DriverObject->MajorFunction[i(=PassThrough;
  "
  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL(=DriverDeviceControl;
  DriverObject->DriverUnload=DriverUnload;
  DriverObject->MajorFunction[IRP_MJ_CREATE(=DriverOpen;
  DriverObject->MajorFunction[IRP_MJ_CLOSE(=DriverClose;
  DriverObject->MajorFunction[IRP_MJ_READ(=ReadDispatchM;
  ntStatus=IoCreateDevice)DriverObject, sizeof)DEVICE_EXTENSION:,
                          NULL, FILE_DEVICE_MOUSE, 0,
                          FALSE, &deviceObjectM:;
  if )!NT_SUCCESS)ntStatus:: |
    IoDetachDevice)extK->TopOfStack:; IoDeleteDevice)deviceObjectK:;
    IoDeleteSymbolicLink)&USLink:; RtlFreeUnicodeString)&USName:;
    return ntStatus;
  "
  extM=)PDEVICE_EXTENSION: deviceObjectM->DeviceExtension;
  RtlZeroMemory)extM, sizeof)DEVICE_EXTENSION::;
  extM->DriverObject=DriverObject; extM->Dev=deviceObjectM;
  deviceObjectM->Flags|=)DO_BUFFERED_IO|DO_POWER_PAGABLE:;
  RtlInitUnicodeString)&USStrM, M_CLASS0:;
  // Attach to the mouse chain.
  ntStatus=IoAttachDevice)deviceObjectM, &USStrM, &extM->TopOfStack:;
  if )ntStatus!=STATUS_SUCCESS: |
    IoDetachDevice)extK->TopOfStack:; IoDeleteDevice)deviceObjectK:;
    IoDeleteDevice)deviceObjectM:; IoDeleteSymbolicLink)&USLink:;
    RtlFreeUnicodeString)&USName:; return ntStatus;
  "
  deviceObjectK->Flags&=~DO_DEVICE_INITIALIZING;
  deviceObjectM->Flags&=~DO_DEVICE_INITIALIZING;
  return STATUS_SUCCESS;
"
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #5 : 04-02-2004 10:53 » 

Зачеми два :!:  раза инициализируешь указатели на ф-ции диспечтеризации? Это не приведет к краху, но выглядит странно.
А это зачем
Цитата

deviceObjectK->Flags|=(DO_BUFFERED_IO|DO_POWER_PAGABLE);

установку флагов надо согласовывать с DEVICE_OBJECT к которому подключаешься, если у него нет DO_POWER_PAGABLE то и тебе не надо, если у него не DO_BUFFERED_IOто и у тебя не должно быть, иначе тебе придется самому преобразовывать StackLocation в IRP.
Особо вникать в твой текст не буду(уж очень сложно ты пишешь Отлично ), но то что у тебя несогласованы флаги- уже это станет одной из причин падения- драйверу нижележащего устройства подсовывают IRP, сделанный по флагам твоих DEVICE_OBJECT, а не его.
Записан
falcon
Гость
« Ответ #6 : 04-02-2004 11:06 » 

Цитата: SlavaI

А можно ли один FDO подключить к нескольким драйверам?
[...]
Тебе и не дадут два драйвера загрузить. А вот сделать два DEVICE_OBJECT из одого драйвера можно.

Попытался сделать так, как ты говоришь, теперь НТюк валится в синий экран при попытке загрузить драйвер.


  Да, с классом я и вправду лихо промахнулся  :oops: .

  Класс я исправил, драйвер нормально грузится, НО все IRP приходят в обработчик мышки, и я так думаю, потому что он последним указан в IRP_MJ_READ.

  Я пытался создать два ФДО, каждый с отдельной функцией IRP_MJ_READ, но ведь обработчик IRP_MJ_READ указывается в DriverObject, а не в ФДО, следовательно, у всех ФДО он будет один и тот же (что я и имею), а следовательно, все возвращается к тому, с чего все началось - нужно определять чей IRP пришел в обработчик. А в чем тогда был смысл создавать два ФДО ?

PS: Кстати, а вот такая штука - на какой device_object будет указывать - на мой FDO ?
PIO_STACK_LOCATION currentIrpStack=IoGetCurrentIrpStackLocation(Irp);
currentIrpStack->DeviceObject

Вот этот DeviceObject и есть мой ФДО, следовательно, если я в его DEVICE_EXTENSION помещу указатель на принадлежность к тому или иному типу, то его-то и можно будет использовать для определения, чей IRP я обрабатываю ?
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #7 : 04-02-2004 11:18 » 

Цитата

 пытался создать два ФДО, каждый с отдельной функцией IRP_MJ_READ, но ведь обработчик IRP_MJ_READ указывается в DriverObject, а не в ФДО, следовательно, у всех ФДО он будет один и тот же (что я и имею), а следовательно, все возвращается к тому, с чего все началось - нужно определять чей IRP пришел в обработчик. А в чем тогда был смысл создавать два ФДО ?


Значит так- в DeviceExtension запоминаешь что ЭТОТ FDO ты подсоединяшь к мыше, например делаешь там флаг и ставишь там MUSH Отлично , а у FDO для клавы ставишь там KLAVA.

extK=(PDEVICE_EXTENSION) deviceObjectK->DeviceExtension;
для FDO мыши-
extK->Flags |= MUSH;
для FDO клавы
extK->Flags |= KLAVA;
И проверяешь этот флаг в во всех обработчиках своего драйвера, если там MUSH то запрос на верхний фильтр FDO мыши, если KLAVA- то к клаве.

Цитата

PIO_STACK_LOCATION currentIrpStack=IoGetCurrentIrpStackLocation(Irp);
currentIrpStack->DeviceObject


Будет указывать на тот, на который послан запрос, поле currentIrpStack->DeviceObject  устанавливает ф-ция IoCallDriver в то значение, которое ей передали.

Цитата

Вот этот DeviceObject и есть мой ФДО, следовательно, если я в его DEVICE_EXTENSION помещу указатель на принадлежность к тому или иному типу, то его-то и можно будет использовать для определения, чей IRP я обрабатываю ?


Именно так. Про что тебе и было сказано.
Но его можно получить проще- это первый параметр в ф-циях обработки кодов IRP_MJ_.., а именно эти ф-ции ты и пишешь в драйвере.
Записан
falcon
Гость
« Ответ #8 : 04-02-2004 12:20 » 

Цитата: SlavaI

Вот этот DeviceObject и есть мой ФДО, следовательно, если я в его DEVICE_EXTENSION помещу указатель на принадлежность к тому или иному типу, то его-то и можно будет использовать для определения, чей IRP я обрабатываю ?

Именно так. Про что тебе и было сказано.
Но его можно получить проще- это первый параметр в ф-циях обработки кодов IRP_MJ_.., а именно эти ф-ции ты и пишешь в драйвере.


Many thanks! Работает! Спасибо!  Отлично
Записан
falcon
Гость
« Ответ #9 : 04-02-2004 14:32 » 

А вот еще вопросец образовался  8)

  Я, на время общения с устройством, блокирую у пользователя клавиатуру и мышь - чтобы нетерпеливый юзверь не грузил систему. Собственно, это неважно. Важно, что для того, чтобы "заткнуть" клавиатуру, я делаю так: Irp->IoStatus.Information=0. В итоге, система считает, что пришло 0 структур KEYBOARD_INPUT_DATA, и не отзывается на нажатие клавиш.
  Я повторил этот же фокус с мышью, и, в принципе, результат меня устроил, но любопытство не дает покоя. Если при обработке "мышиного" ИРП делать Irp->IoStatus.Information=0, то если подергать мышкой, курсор медленно ползет по той оси и в ту сторону, куда двигался в последний раз, пока не упрется в край экрана, и там уже "умирает" окончательно.

  В принципе, меня это устраивает, но все же - почему?
  Если я обнуляю объем данных в ИРП, то откуда система узнает о том, что мышь двигалась ?   Я шокирован!
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #10 : 04-02-2004 14:41 » 

Цитата

Irp->IoStatus.Information=0.


Не очень хорошо так делать, если ты это делаешь на уже отработавшем IRP- может остаться неосвобожденная память. Лучше отклонять запрос еще на уровне своего драйвера с каким нибудь кодом завершения, сигнализирующем о запрете, ошибке и т.д естественно при этом надо сделать Irp->IoStatus.Information=0.

Цитата

Если я обнуляю объем данных в ИРП, то откуда система узнает о том, что мышь двигалась ?


Без понятия, скорее всего ты создал необрабатываемую последовательность действий, вобще-то я отрубал мышь простым отклонением запросов на уровне класс драйвера.
Записан
falcon
Гость
« Ответ #11 : 05-02-2004 08:01 » 

Цитата: SlavaI
Irp->IoStatus.Information=0.

Не очень хорошо так делать, если ты это делаешь на уже отработавшем IRP- может остаться неосвобожденная память. Лучше отклонять запрос еще на уровне своего драйвера с каким нибудь кодом завершения, сигнализирующем о запрете, ошибке и т.д естественно при этом надо сделать Irp->IoStatus.Information=0.


Во время обработки моим драйвером я задаю IoSetCompletionRoutine, и в своей процедуре завершения ИРП обнуляю объем данных, которые вернул драйвер. Я ведь не трогаю irpStack->Parameters.DeviceIoControl.OutputBufferLength, то есть не трогаю объем памяти, выделенный под данные. Разве из-за этого могут быть утечки памяти?

  И еще - Completion routine я задаю специально, потому что в ДДК сказано, что intermediate драйвер не должен пытаться отменить проходящие через него IRP, если эти ИРП созданы не им(драйвером) самим, потому что можно отменить ИРП, который для каких-либо своих нужд отслеживает high-level driver.

  Вот я и подумал, что корректнее будет, задавать обработчик completionRoutine, и ужЕ там обнулять данные. (Или еще можно попробовать IoCancelIrp в этом же обработчике вместо Irp->IoStatus.Information=0. )

  Или я неправ?
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #12 : 05-02-2004 08:58 » 

Цитата

Или я неправ?


Наверно прав. Но ты меня наверно не так понял. Я тебе говорил не отменять(IoCancelIrp), а завершать IoCompleteRequest еще в своем драйвере., IRP не будет уничтожен, верхний драйвер получит только неуспешный код завершения. Я наверно написал отменять- ты и понял буквально.
Но тем не менее иногда единственный вариант- только завершение с  IoCompleteRequest , например в фильтрах файловых систем пропускать IRP нельзя, иначе будут изменены данные на диске. Я предпочитаю разворачивать(IoCompleteRequest) IRP еще на своем драйвере, так как не вижу особого смысла в отмене в процедуре завершения.
 Тут надо каждый случай рассматривать- в некоторых IRP в поле  Irp->IoStatus.Information может быть указатель на буфер, например в IRP_MN_QUERY_DEVICE_RELATIONS, если его переписать- не будет освобождена память.

IoCancelIrp конечно применять не стоит.
Записан
Anonymous
Гость
« Ответ #13 : 05-02-2004 12:14 » 

Цитата: SlavaI

предпочитаю разворачивать(IoCompleteRequest) IRP еще на своем драйвере, так как не вижу особого смысла в отмене в процедуре завершения.


  Покажи как. Я попробовал - ничего хорошего не вышло, хотя я, честно говоря, особо не разбирался.
  Вот мой пример - первая же попытка блокировать ИРП приводит к отваливанию клавы.
NTSTATUS ReadDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  PDEVICE_EXTENSION  ext;

  ext=(PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  if ((ext->MyFDOType==TYPE_KB&&KLocked)||(ext->MyFDOType==TYPE_MOU&&MLocked)) {
    Irp->IoStatus.Status=STATUS_ACCESS_DENIED;
    Irp->IoStatus.Information=0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS; // STATUS_ACCESS_DENIED тоже пробовал - без разницы
  }
  IoSkipCurrentIrpStackLocation(Irp);
  return IoCallDriver(ext->TopOfStack, Irp);
}
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #14 : 05-02-2004 13:20 » 

Цитата

Покажи как


Также как и у тебя. Только я на класс драйвере разворачивал для USB клавы, там фильтр стоял- часть отклонял, часть нет, наверно поэтому и не отрубалась, и там нельзя было ставить CompletionRoutine- ее уже до меня поставили в тот StackLocation.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines