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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: USB драйвер фильтр для flash-memory  (Прочитано 23183 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Yarilo
Гость
« : 13-08-2003 13:14 » 

Написав этот драйвер фильтр сталкнулся со следующей ситуацией.
Драйвер мой правильно расположился в стеке над usbhub.sys и под usbstore.sys,
т.е. все запросы к флешке я ловлю, но вот появилась проблема:
1) код драйвера фильтра выполняется на IRQL = DISPATCH, почему? И какие объекты синхронизации можно применять в этом случае? (FastMutex точно нельзя)
2) Для того чтобы получить результат после обработки запроса IRP_MJ_INTERNAL_DEVICE_CONTROL я так понимаю мне нужно позвать драйвер синхронно. (Не понялНе понял) Ну я это пытаюсь сделать через событие и IoSetCompletionRoutine, причем вызов выполняется и возвращается STATUS_SUCCESS. Но почему-то все зависает, такое ощещение, что Usbstore.sys ждет STATUS_PENDING. Что делать?
Может кто сталкивался с такой проблемой, напишите?

С уважением Ярослав.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #1 : 13-08-2003 13:42 » 

Цитата

 код драйвера фильтра выполняется на IRQL = DISPATCH


Для USB это нормально. По всей видимости связано с тем, что IRP сидят в очереди и вызываются с помощью IoStartNextPacket. Мне этот вопрос тоже интересен, так что если для тебя очень важно знать почему- я разберусь.

Цитата

Для того чтобы получить результат после обработки запроса IRP_MJ_INTERNAL_DEVICE_CONTROL я так понимаю мне нужно позвать драйвер синхронно. (Не понялНе понял) Ну я это пытаюсь сделать через событие и IoSetCompletionRoutine, причем вызов выполняется и возвращается STATUS_SUCCESS. Но почему-то все зависает, такое ощещение, что Usbstore.sys ждет STATUS_PENDING


Тут я не понял, что ты имеешь в виду. Причем тут USBSTOR, если ты под ним? Привел бы лучше код - как ты вызываешь нижний драйвер, как выглядит процедура завершения и т.д.

Цитата

ждет STATUS_PENDING


Тут с формулировкой что-то не то. Что имел в виду-то,
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #2 : 13-08-2003 13:58 » 

А кажется понял- ты хочешь возвратить STATUS_PENDING в USBSTOR. Так это же просто- возьми и возврати его до вызова нижнего драйвера с кодом IRP_MJ_INTERNAL_DEVICE_CONTROL, а обработку(то есть вызов драйвера) сделай в отдельном потоке, то есть вызови нижний драйвер в отдельном потоке, все чисто будет и IRQL==PASSIVE. Но только по моему мнению это не должно влиять на правильность работы, то есть как я уже говорил- приведи коды.

Цитата

DISPATCH, почему? И какие объекты синхронизации можно применять в этом случае?


 На DISPATCH_LEVEL можно применять спин блокировки, и больше ничего.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #3 : 13-08-2003 14:09 » 

По моему в этом и вопрос - что возвращать PENDING или SUCCESS.
Имхо там все же должен быть PENDING - ибо система сама должна освобождать данные.
Записан

А птичку нашу прошу не обижать!!!
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #4 : 13-08-2003 14:14 » 

Цитата

должен быть PENDING - ибо система сама должна освобождать данные.


А какая связь между PENDING и освобождением данных(ресурсов). По мне- так никакой. И мое мнение- не важно что возвращать при корректно написанном верхнем драйвере.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #5 : 13-08-2003 14:19 » 

Как я помню в случае отработки пакета данных возвращается по условию или PENDING или SUCCESS в зависимости от окончания или не окончания полной отработки данных.
Скрытый смысл точного механизма от меня скрыт пока, но как я понял - получив PENDING система вызывает Completion Routine дабы окончить системную обработку и отпустить ресурс.

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

Этот механизм был нужен для того, что бы не замедлять работу ядра, когда сам драйвер вынужден логически приостановить процесс обработки данных.

В этом случае так и происходит.
Записан

А птичку нашу прошу не обижать!!!
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #6 : 13-08-2003 14:21 » 

то есть вот так сделай

{
........
SetIrpInQueue(Irp, Context);//эту ф-цию сам пиши
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}

а в отдельном потоке, вынимай IRP из очереди и обрабатывай как хочешь, а потом вызывай нижний драйвер.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #7 : 13-08-2003 14:23 » 

Цитата

но как я понял - получив PENDING система вызывает Completion


Система(или сам драйвер- это не важно) вызывает CompletionRoutine всегда- она вызывается из IoCompleteRequest, подробности в моей статье на этом сайте.
PENDING говорит только о том, что надо поставить APC в нужный контекст, опять же подробности в моей статье.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #8 : 13-08-2003 14:27 » 

Тогда смысл объявлять IRP как PENDING физически если я уже закончил с ним работать?
В моем драйвере стоял в случае SUCCESS код Completion Routine и потом возврат SUCCES а если не смогли пройти процедуры завершения - возвращался PENDING.
Записан

А птичку нашу прошу не обижать!!!
Yarilo
Гость
« Ответ #9 : 13-08-2003 14:58 » 

Извините за задержку, не думал, что Вы так быстро отреагируете Улыбаюсь
Привожу фрагмент кода:
Код:
NTSTATUS 
UsbSniffHookRoutine(
    PDEVICE_OBJECT HookDevice,
    IN PIRP Irp
    )
{
        PHOOK_EXTENSION hookExt = NULL;
PIO_STACK_LOCATION currentIrpStack = NULL;
UCHAR majorFunction;
BOOLEAN passIrpDown = TRUE;
NTSTATUS ntStatus;

currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
majorFunction = currentIrpStack -> MajorFunction;

hookExt = HookDevice -> DeviceExtension;

switch(majorFunction)
{
//-------------------------------------------
//SKIPED
//-------------------------------------------
case IRP_MJ_INTERNAL_DEVICE_CONTROL:

// синхронно вызываем этот запрос
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = UsbSniffCallNextDriverSync(hookExt, Irp);

passIrpDown = FALSE;

break;
}

if(passIrpDown)
{
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(hookExt -> topUsbDevice, Irp);
}

return ntStatus;
}


UsbSniffCallDriverSyncCompletion(
IN PDEVICE_OBJECT hookUsbDevice,
IN PIRP Irp,
IN PVOID context)

{
    PKEVENT event = context;
ASSERT(Irp -> IoStatus.Status != STATUS_IO_TIMEOUT);
KeSetEvent(event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
UsbSniffCallNextDriverSync(
PHOOK_EXTENSION hookExt,
PIRP Irp
)
{
KEVENT event;
NTSTATUS ntStatus;

KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine( Irp,
                            UsbSniffCallDriverSyncCompletion,
                            &event,
                            TRUE, TRUE, TRUE);
ntStatus = IoCallDriver(hookExt -> topUsbDevice, Irp);
    KeWaitForSingleObject(  &event,
                            Executive,
                            KernelMode,
                            FALSE,
                            NULL);

    ntStatus = Irp -> IoStatus.Status; // здесь всегда возвращается 0
// причем подряд должны идти запросов 10, а получается, что на 1-м все //останавливается и все висит, даже файловый менеджер в котором я пытаюсь //достучаться до flash-а

Спасибо за внимание, с уважением Ярослав.
ASSERT(NT_SUCCESS(ntStatus));
return ntStatus;
}
« Последнее редактирование: 19-11-2007 16:44 от Алексей1153++ » Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #10 : 14-08-2003 04:52 » 

Цитата

В моем драйвере стоял в случае SUCCESS код Completion Routine и потом возврат SUCCES а если не смогли пройти процедуры завершения
 - возвращался PENDING.


И что ты после PENDING делал? Возврат PENDING означает, что отложили обработку IRP, но не отменили, не с какими ошибками PENDING не может быть связан. Если есть ошибка- то ее и надо возвращать. Если возвратить PENDING и не вызвать позже для IRP IoCompleteRequest или не послать нижележащему драйверу, то оно так и останется в системе, отнимая память.

И что-то я логику не пойму, откуда ты возвращал PENDING, вот ты пишешь "не смогли пройти процедуры завершения", ты из CompletionRoutine возвращал PENDING- так это неправильно, из процедуры завершения допустимо возвращать только SUCCESS или STATUS_MORE_PROCESSING_REQUIRED.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #11 : 14-08-2003 04:58 » 

Цитата
SetIrpInQueue(Irp, Context);//эту ф-цию сам пиши
IoMarkIrpPending(Irp);
return STATUS_PENDING

Я тут немного лажанулся, надо всегда вот так делать
 
Код:
IoMarkIrpPending(Irp); 
SetIrpInQueue(Irp, Context);//эту ф-цию сам пиши
return STATUS_PENDING;

а то может так выйти, что IRP обработают в другом потоке, раньше чем ты его пометишь IoMarkIrpPending(Irp), что приведет или к подвисанию системы или к ее краху, так как при завершении IRP не будет известно, что его запендили, то есть контекст потока для APC неверный будет.
« Последнее редактирование: 19-11-2007 16:46 от Алексей1153++ » Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #12 : 14-08-2003 05:14 » 

to Yarlio.
Давай теперь с твоим кодом разбираться.
Смотрим на твою процедуру завершения, в ней все нормально-возвращает она STATUS_MORE_PROCESSING_REQUIRED, что означает, что IoCompleteRequest, прерывает раскрутку стека на твоем драйвере и никогда не завершит этот IRP( кстати можешь почитать мою статейку на этом сайте про процедуру IoCompleteRequest), чтобы завершить этот IRP тебе надо самому вызвать IoCompleteRequest в твоем драйвере. Поэтому все и висит, IRP не завершен и следующий не ставится на обработку.
Надо или возвращать STATUS_SUCCESS из процедуры завершения, или самому закомплитить IRP например вот так

UsbSniffCallNextDriverSync
{
.............
ntStatus = Irp -> IoStatus.Status;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

ASSERT(NT_SUCCESS(ntStatus));
return ntStatus;
}

И у тебя еще одно упущение в процедуре завершения- в самом начале надо написать
 if (Irp->PendingReturned)
    IoMarkIrpPending(Irp);
иначе система может подвиснуть. Но в твоем случае, этот заголовок в принципе не нужен.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #13 : 14-08-2003 08:15 » 

SlavaI, не ты не понял.
Идет сначала захват пакета, работа с ним, потом отдача.
Попытка отдать пакет - завершить пакетную обработку завершается, функция возвращает не SUCCESS т.е. отдать пакет невозможно , тогда PENDING.
Комплетион рутина вызывается самой системой.
Если все ОК и отдать пакет системе смогли, то тогда вперед, возврат SUCCESS..
Погоди я код посмотрю.
Записан

А птичку нашу прошу не обижать!!!
Yarilo
Гость
« Ответ #14 : 14-08-2003 12:44 » 

Спасибо огромное, как раз именно в этом и была трабла   Улыбаюсь

Как только я применил:

UsbSniffCallNextDriverSync
{
.............
ntStatus = Irp -> IoStatus.Status;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

ASSERT(NT_SUCCESS(ntStatus));
return ntStatus;
}

пакеты начали передаваться и висняк прошел. Но вот одно но:
иногда выплывает assertion, при этом
ntStatus == STATUS_MORE_PROCESSING_REQUIRED

это нормально и просто на это не обращать внимание? Т.е. я так понимаю какой-то верхний драйвер еще не выполнил свою IoCompleteRoutine? Или все же нужно обратить на это внимание?

С уважением Ярослав.
Yarilo_@mail.ru
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #15 : 14-08-2003 12:56 » 

Цитата

пакеты начали передаваться и висняк прошел. Но вот одно но:
иногда выплывает assertion, при этом
ntStatus == STATUS_MORE_PROCESSING_REQUIRED

это нормально и просто на это не обращать внимание? Т.е. я так понимаю какой-то верхний драйвер еще не выполнил свою IoCompleteRoutine? Или все же нужно обратить на это внимание?


Ну если это не твой драйвер такой код ставит, то пусть так и остается. Я так понимаю такой код у тебя вылезает в UsbSniffCallNextDriverSync, если да- то это результат отработки нижнего драйвера. В процедурах завершения не принято менять статус завершения. Верхний драйвер тут точно ни при чем, ты же получаешь статус возврата до вызова IoCompleteRequest, после вызова получать статус завершения нельзя, так как IRP может уже не быть.
Записан
Yarilo
Гость
« Ответ #16 : 14-08-2003 13:17 » 

Да это происходит именно в функции UsbSniffCallNextDriverSync.
Насколько я понял возврат значения ntStatus равное STATUS_MORE_PROCESSING_REQUIRED в этом случае является  допустимым и мне нужно, чтобы не выплывало это assertion просто изменить проверку значения на:
UsbSniffCallNextDriverSync
{
.............
ntStatus = Irp -> IoStatus.Status;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
ASSERT(NT_SUCCESS(ntStatus) || (ntStatus == STATUS_MORE_PROCESSING_REQUIRED));
return ntStatus;
}
Это так?
Записан
Anonymous
Гость
« Ответ #17 : 15-08-2003 06:45 » 

Цитата

Это так?


Да так. Хотя такой возвращенный код мне не нравится.
А почему ты назвал нижележащий драйвер topUsbDevice, лучше lowerUsbDevice, принято считать, что запрос снизу вверх идет, а то путаница в терминах выходит, будут непонимать тебя.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #18 : 15-08-2003 07:48 » 

Предшествующий пост- мой, не залогинился.
Записан
Yarilo
Гость
« Ответ #19 : 18-08-2003 07:38 » 

OK.
Драйвер заработал, но вот есть один баг, который я не знаю как пофиксить. А именно:
Если я активизирую драйвер во время передачи файлов, то в месте
NTSTATUS
UsbSniffCallNextDriverSync(
PHOOK_EXTENSION hookExt,
PIRP Irp
)
{
...
KeWaitForSingleObject( &event,
Executive,
KernelMode,
FALSE,
NULL);
...
}
возникает ошибка: ATTEMPTED_SWITCH_FROM_DPC, как этого избежать? Ждать очищения очереди DPC ?
Название topUsbDevice было использовано, т.к. в момент присоединения это устройство было верхнее в стеке. Но это не принципиально.

С уважением Ярослав.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #20 : 18-08-2003 08:01 » 

Цитата

 ATTEMPTED_SWITCH_FROM_DPC,


Никакая очистка очереди тебе не поможет, так как драйвер вызывают из DPC процедуры.
Ждать на IRQL==DISPATCH(на котором DPC и вызываются) с ненулевым временем нельзя, так как происходит попытка перепланировки потоков, а вызов планировщика из DPC(которая работает на уровне DISPATCH) невозможен.  Это означает, что синхронную обработку тебе на DISPATCH уровне не сделать, так как ты остановиш планировщик на том из процессоров, уровень которого >=DISPATCH, а при одном процессоре в системе это означает остановку всей системы на бесконечное время.

Варианты- возвращать STATUS_PENDING и отложить вызов драйвера в отдельный поток, или просто вызвать драйвер.
Записан
Yarilo
Гость
« Ответ #21 : 18-08-2003 08:37 » 

Что подразумевается под:
или просто вызвать драйвер
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #22 : 18-08-2003 08:54 » 

Цитата
Что подразумевается под:
или просто вызвать драйвер

не использовать UsbSniffCallNextDriverSync, а сразу вызвать драйвер

return IoCallDriver(...);

для проверки сделай так
Код:
	CurrentIrql = KeGetCurrentIrql();

switch (CurrentIrql)
{
case PASSIVE_LEVEL:
case APC_LEVEL:
                      UsbSniffCallNextDriverSync(....);
                      ....;
                      break;
case DISPATCH_LEVEL:
                     return IoCallDriver(....);
                }
« Последнее редактирование: 19-11-2007 16:49 от Алексей1153++ » Записан
Евгений
Гость
« Ответ #23 : 27-03-2008 08:13 » 

Подскажите, у меня похожаю задача. какой именно фильтр из DDK подойдет для примера. или если можно код этого фильтра. прошу, подскажите.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines