Я перехватываю Paging I/O IRP_MJ_READ ставлю на этот Irp свою CompletionRoutine и посылаю Irp вниз IoCallDriver. Когда происходит вызов CompletionRoutine в буфере MmGetSystemAddressForMdlSafe(Irp->MdlAdress) нет данных. При этом если вызвать IoCallDriver и там же в обработчике дождаться его завершения и посмотреть MmGetSystemAddressForMdlSafe(Irp->MdlAdress), то данные там есть, но насколько я понимаю это не корректно, так как мне затем нужно менять содержимое этого буфера. Кроме того примеры реализации через CompletionRoutine встречал на ntfsd.org, но у меня не работает.
P.S.: IFS kit не имею и наверное иметь не буду, просьба ссылками на него не кидаться
... << RSDN@Home 1.0 beta 7a >>
Re: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
U>Я перехватываю Paging I/O IRP_MJ_READ ставлю на этот Irp свою CompletionRoutine и посылаю Irp вниз IoCallDriver. Когда происходит вызов CompletionRoutine в буфере MmGetSystemAddressForMdlSafe(Irp->MdlAdress) нет данных. При этом если вызвать IoCallDriver и там же в обработчике дождаться его завершения и посмотреть MmGetSystemAddressForMdlSafe(Irp->MdlAdress), то данные там есть, но насколько я понимаю это не корректно, так как мне затем нужно менять содержимое этого буфера. Кроме того примеры реализации через CompletionRoutine встречал на ntfsd.org, но у меня не работает.
в обработчике можно ждать и модифицировать данные после того как Вы их получили от нижнего драйвера, все корректно
по поводу отсутствия буфера:
буфер не всегда лежит в Irp->MdlAddress.
проверяйте у себя еще Irp->UserBuffer
if (NULL == Irp->MdlAddress)
{
//
//if the Mdl of Irp is NULL, we have to deal with UserBuffer,
//taking into account the Process of the request, since virtual addresses
//are valid only in particular process contexts.
//if (Irp->UserBuffer == NULL)
{
IoStatus->Status = STATUS_UNSUCCESSFUL;
IoStatus->Information = 0;
return;
}
}
... << RSDN@Home 1.1 alpha 1 >>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[2]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
Здравствуйте, Valerio, Вы писали:
V>в обработчике можно ждать и модифицировать данные после того как Вы их получили от нижнего драйвера, все корректно
У меня после return STATUS_SUCCESS; система повисала, чему кажется есть оправдание — все отработали (event показал), I/O Manager "закончил" свои дела, а я вдруг начинаю модифицировать, если при этом делать IoComleteRequest все работает, но это же не правильно ?
V>по поводу отсутствия буфера: V>буфер не всегда лежит в Irp->MdlAddress. V>проверяйте у себя еще Irp->UserBuffer
Irp->MdlAddress не NULL (Кстати, а почему это может быть ?), вот в этом то вся и беда . Если видели мой пост в этой ветке я привел архивы ntfsd.org, в них Tony Mason "открыл" людям глаза на эту проблему, но до меня если честно так и не дошло как решить эту проблему, может кто-то понятливей меня
... << RSDN@Home 1.0 beta 7a >>
Re: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
От:
Аноним
Дата:
15.07.03 06:31
Оценка:
Здравствуйте, unintruder, Вы писали:
Советую почитать Q320275,Q326315
В Q320275 обратить внимание на Scenario 4.
Re[3]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
U>У меня после return STATUS_SUCCESS; система повисала, чему кажется есть оправдание — все отработали (event показал), I/O Manager "закончил" свои дела, а я вдруг начинаю модифицировать, если при этом делать IoComleteRequest все работает, но это же не правильно ?
так надо все же подождать пока Ваш completion не отработает и затем уже возвращать статус IO Manager.
V>>по поводу отсутствия буфера: V>>буфер не всегда лежит в Irp->MdlAddress. V>>проверяйте у себя еще Irp->UserBuffer
U>Irp->>MdlAddress не NULL (Кстати, а почему это может быть ?), вот в этом то вся и беда . Если видели мой пост в этой ветке я привел архивы ntfsd.org, в них Tony Mason "открыл" людям глаза на эту проблему, но до меня если честно так и не дошло как решить эту проблему, может кто-то понятливей меня
Кстати не читал соседний пост
да, известная фишка — если устанавливаете свой MDL в Irp->MdlAddress- надо бы и UserBuffer выставить в то же значение. Вам вполне может подобный запрос сверху прилететь.
совет же говорит что нужно все модификации делать в своем буфере и все будет хорошо.
собственно и я обычно то же самое советую — при запросах на запись все равно без этого никак (вызывающему может не понравиться если у него вдруг данные волшебным образом изменятся )
на чтение сгодится и вот так (Вы поддерживаете partial MDL?):
PMDL mdl = NULL;
int len = Irp->IoStatus.Information;
int MdlProcessed = 0;
BOOLEAN mdlAllocated = FALSE;
__try
{
if (NULL == Irp->MdlAddress)
{
//
//if the Mdl of Irp is NULL, we have to deal with UserBuffer,
//taking into account the Process of the request, since virtual addresses
//are valid only in particular process contexts.
//if (Irp->UserBuffer == NULL)
{
IoStatus->Status = STATUS_UNSUCCESSFUL;
IoStatus->Information = 0;
return;
}
//
//attach to the valid process context
//
KeAttachProcess(Process);
//
//allocate an MDL
//
mdl = IoAllocateMdl(Irp->UserBuffer,len,FALSE,FALSE,NULL);
//
//switch back to the current process
//
KeDetachProcess();
if(mdl == NULL)
{
IoStatus->Status = STATUS_UNSUCCESSFUL;
IoStatus->Information = 0;
return;
}
__try
{
MmProbeAndLockPages(mdl,KernelMode,IoModifyAccess);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
IoStatus->Status = STATUS_UNSUCCESSFUL;
IoStatus->Information = 0;
return;
}
mdlAllocated = TRUE;
}
else
{
mdl = Irp->MdlAddress;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
IoStatus->Status = STATUS_UNSUCCESSFUL;
IoStatus->Information = 0;
}
while(mdl)
{
//
//get the virtual addrees for Mdl
//#if (_WIN32_WINNT<0x0500)
PCHAR buffer = MmGetSystemAddressForMdl(mdl);
#else
PCHAR buffer = MmGetSystemAddressForMdlSafe(mdl,HighPagePriority);
#endif
PMDL MdlNext= mdl->Next;
int ChainLen=MmGetMdlByteCount(mdl);
if (MdlProcessed+ChainLen>len)
{
ChainLen=len-MdlProcessed;
}
//doing your buffer modification here
MdlProcessed+=ChainLen;
//
//if we had to allocate mdl previously, free it.
//if(mdlAllocated)
{
MmUnlockPages(mdl);
IoFreeMdl(mdl);
}
mdl = MdlNext;
}
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = len;
P.S. по поводу оригинальной проблемы: Вы под verifier получаете взрыв? попробуйте без него.
... << RSDN@Home 1.1 beta 1 >>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[4]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
Здравствуйте, Valerio, Вы писали:
U>>У меня после return STATUS_SUCCESS; система повисала, чему кажется есть оправдание — все отработали (event показал), I/O Manager "закончил" свои дела, а я вдруг начинаю модифицировать, если при этом делать IoComleteRequest все работает, но это же не правильно ?
V>так надо все же подождать пока Ваш completion не отработает и затем уже возвращать статус IO Manager.
Здесь речь идет о том возможно ли делать модификацию в dispatch routine (IRP_MJ_READ). Вы высказались что, да это не проблема. Так вот я дожидаюсь выполнения своего Completion,
status = ForwardIrpSynchronous(pDevice,pIrp); //wrap IoCallDriver(pIrp)
вызываю return и система висит. Если перед ретурн вызываю
то все работает, но это же нельзя. Именно по этой причине и пытаюсь обработать pIrp в Completion (что собственно видимо есть правило для IRP_READ), а не удовлетворяющий меня Irp->MdlAdress ( !=NULL )
V>P.S. по поводу оригинальной проблемы: Вы под verifier получаете взрыв? попробуйте без него.
без него
Re[2]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, unintruder, Вы писали:
А>Советую почитать Q320275,Q326315 А>В Q320275 обратить внимание на Scenario 4.
Типичное не то. Может я не ясно выразился в вопросе, еще раз:
Первый сценарий
1. Paging I/O
2. Я получил IRP_MJ_READ , в Irp->MdlAdress пусто
3. Посылаем вниз, дожидаемся выполнения своей Completion (через event), чтобы убедиться что в Irp->MdlAdress нужные нам данные.
4. Меняю данные в этом буфере
5. Вызываю return STATUS_SUCCESS
6. Повисаю.
Второй сценарий (в силу того что первый не сработал и по видимому второй рулез)
1. Paging I/O
2. Я получил IRP_MJ_READ , в Irp->MdlAdress пусто
3. Ставим Completion, посылаем вниз.
4. Дожидаемся в своей Completion, чтобы убедиться что в Irp->MdlAdress (!=NULL) нужные нам данные их там нет
5. Я смеялся
Re[5]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
U>Здесь речь идет о том возможно ли делать модификацию в dispatch routine (IRP_MJ_READ). Вы высказались что, да это не проблема. Так вот я дожидаюсь выполнения своего Completion,
мой код приведенный выше работает не из completion а из dispatch routine как раз по следующему сценарию:
1. Set the completion routine — нужна для того чтобы определить когда закончится IoCallDriver.
(в ней вернуть надо STATUS_MORE_PROCESSING_REQUIRED и KeSetEvent)
2. call the target FSD
3. if ( statusFsd == STATUS_PENDING ) //ждем пока наш completion отработает на событии которое в completion будет установлено!! этого я у Вас не видел — хотя Вы написали что ждете
4. теперь мы имеем ситуацию — нижний драйвер отработал и нам нужно модифицировать буфера как я уже написал
5. если запрос еще не был завершен (в случае неудачного вызова пред драйвера например), то надо завершить самим и вернуть статус
вроде бы все
... << RSDN@Home 1.1 beta 1 >>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[6]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
Здравствуйте, Valerio, Вы писали:
U>>Здесь речь идет о том возможно ли делать модификацию в dispatch routine (IRP_MJ_READ). Вы высказались что, да это не проблема. Так вот я дожидаюсь выполнения своего Completion,
V>мой код приведенный выше работает не из completion а из dispatch routine как раз по следующему сценарию:
V>1. Set the completion routine — нужна для того чтобы определить когда закончится IoCallDriver. V>(в ней вернуть надо STATUS_MORE_PROCESSING_REQUIRED и KeSetEvent) V>2. call the target FSD V>3. if ( statusFsd == STATUS_PENDING ) //ждем пока наш completion отработает на V>событии которое в completion будет установлено!! этого я у Вас не видел — хотя Вы V>написали что ждете
status = ForwardIrpSynchronous(pDevice,pIrp); //wrap IoCallDriver(pIrp)
Это и есть все что вы написали (кажется в Xp DDK что-то похожее реализовано), а далее трабл:
вызываю return и система висит. Если перед ретурн вызываю
то все работает, но это же нельзя. Именно по этой причине и пытаюсь обработать pIrp в Completion (что собственно видимо есть правило для IRP_READ), а не удовлетворяющий меня Irp->MdlAdress ( !=NULL )
И еще вопросик, а зачем нужны partial MDl я их не юзаю и пока не чувствовал потребности ?
... << RSDN@Home 1.0 beta 7a >>
Re[3]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
От:
Аноним
Дата:
15.07.03 11:47
Оценка:
Здравствуйте, unintruder, Вы писали:
U>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, unintruder, Вы писали:
А>>Советую почитать Q320275,Q326315 А>>В Q320275 обратить внимание на Scenario 4.
U>Типичное не то.
Там просто описанны сценарии — согласен.
А насчет Irp->MdlAdress могу сказать он используется только тогда при IRP_MJ_READ и IRP_MJ_READ — если driver установил что device object использует direct I/O.
Вам сначала надо проверить Flags чему он равен DO_BUFFERED_IO или DO_DIRECT_IO
Здравствуйте, <Аноним>, Вы писали:
А>А насчет Irp->MdlAdress могу сказать он используется только тогда при IRP_MJ_READ и IRP_MJ_READ — если driver установил что device object использует direct I/O.
А>Вам сначала надо проверить Flags чему он равен DO_BUFFERED_IO или DO_DIRECT_IO
А>DO_BUFFERED_IO ---- Irp->AssociatedIrp.SystemBuffer А>DO_DIRECT_IO ---- Irp->MdlAddress
Я даже более того скажу — Я САМ установил этот флаг при создании своего устройства .
А вообще, одним словом,у меня Paging I/O — это достаточное условие чтобы ждать данные в Irp->MdlAdress
... << RSDN@Home 1.0 beta 7a >>
Re[7]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
U>то все работает, но это же нельзя. Именно по этой причине и пытаюсь обработать pIrp в Completion (что собственно видимо есть правило для IRP_READ), а не удовлетворяющий меня Irp->MdlAdress ( !=NULL )
скорее всего проблема в драйвере который Вы вызываете:
он по какой то причине не удосужился-не успел еще завершить запрос?
ну а если не успел — тогда разбирайтесь почему Вы его не дожидаетесь...
впрочем, попробуйте OSR IrpTracker (сам не пользовался но судя по описанию может помочь)
U>И еще вопросик, а зачем нужны partial MDl я их не юзаю и пока не чувствовал потребности ?
что значит зачем?
от системы они такие могут прийти в любой момент и надо быть к этому готовым.
... << RSDN@Home 1.1 beta 1 >>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.