falcon
Гость
|
|
« : 03-02-2004 14:35 » |
|
А можно ли один FDO подключить к нескольким драйверам? Иными словами, теоретически я могу сделать IoAttachDevice, например, два раза, подключив свой фдо к нескольким драйверам, тогда в мой обработчик ИРП будут попадать ИРПшки от обоих драйверов, к которым я подключился. Можно ли как-либо определить, чей ИРП пришел в мой обработчик?
А то нехочется грузить два своих драйвера для, в общем-то, одной и той же цели...
|
|
|
Записан
|
|
|
|
Maaaaaaaaad
Гость
|
|
« Ответ #1 : 03-02-2004 16:59 » |
|
Можно ли как-либо определить, чей ИРП пришел в мой обработчик
Вроде через стек локейшн можно определять указатель на девайс обжект
|
|
|
Записан
|
|
|
|
falcon
Гость
|
|
« Ответ #2 : 03-02-2004 17:38 » |
|
Можно ли как-либо определить, чей ИРП пришел в мой обработчик Вроде через стек локейшн можно определять указатель на девайс обжект А примерчик можно ?
|
|
|
Записан
|
|
|
|
SlavaI
Главный специалист
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 » |
|
А можно ли один 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
Главный специалист
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 » |
|
А можно ли один 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
Главный специалист
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 » |
|
Вот этот 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
Главный специалист
Offline
|
|
« Ответ #10 : 04-02-2004 14:41 » |
|
Irp->IoStatus.Information=0.
Не очень хорошо так делать, если ты это делаешь на уже отработавшем IRP- может остаться неосвобожденная память. Лучше отклонять запрос еще на уровне своего драйвера с каким нибудь кодом завершения, сигнализирующем о запрете, ошибке и т.д естественно при этом надо сделать Irp->IoStatus.Information=0. Если я обнуляю объем данных в ИРП, то откуда система узнает о том, что мышь двигалась ?
Без понятия, скорее всего ты создал необрабатываемую последовательность действий, вобще-то я отрубал мышь простым отклонением запросов на уровне класс драйвера.
|
|
|
Записан
|
|
|
|
falcon
Гость
|
|
« Ответ #11 : 05-02-2004 08:01 » |
|
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
Главный специалист
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 » |
|
предпочитаю разворачивать(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
Главный специалист
Offline
|
|
« Ответ #14 : 05-02-2004 13:20 » |
|
Покажи как
Также как и у тебя. Только я на класс драйвере разворачивал для USB клавы, там фильтр стоял- часть отклонял, часть нет, наверно поэтому и не отрубалась, и там нельзя было ставить CompletionRoutine- ее уже до меня поставили в тот StackLocation.
|
|
|
Записан
|
|
|
|
|