Проблема CompletionRoutine на Irp (IRP_MJ_READ)
От: unintruder  
Дата: 11.07.03 05:37
Оценка:
Я пишу фильтр файловой системы:

Я перехватываю 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)
От: 1010  
Дата: 11.07.03 10:54
Оценка:
Здравствуйте, unintruder, Вы писали:

Может это поможет?
windowsdriver
Re[2]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
От: unintruder  
Дата: 11.07.03 12:13
Оценка:
Здравствуйте, 1010, Вы писали:

1>Здравствуйте, unintruder, Вы писали:


1>Может это поможет?

1>windowsdriver

думаю нет

Вот здесь
http://www.ntfsd.org/archive/ntfsd0211/msg0208.html
http://www.ntfsd.org/archive/ntfsd0211/msg0222.html
обсуждается похожая проблема, но я прочитав все посты по этой ветке так и не понял, как она решается ? Вопрос к людям на практике сталкивавшихся с этой проблемой.
Re: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
От: Valerio Россия linkedin.com/in/boronin
Дата: 12.07.03 06:06
Оценка:
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)
От: unintruder  
Дата: 15.07.03 06:21
Оценка:
Здравствуйте, 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)
От: Valerio Россия linkedin.com/in/boronin
Дата: 15.07.03 06:55
Оценка:
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)
От: unintruder  
Дата: 15.07.03 10:31
Оценка:
Здравствуйте, 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->IoStatus.Status = STATUS_SUCCESS;
      pIrp->IoStatus.Information = Size;
      IoCompleteRequest(pIrp,IO_NO_INCREMENT);


то все работает, но это же нельзя. Именно по этой причине и пытаюсь обработать pIrp в Completion (что собственно видимо есть правило для IRP_READ), а не удовлетворяющий меня Irp->MdlAdress ( !=NULL )

V>P.S. по поводу оригинальной проблемы: Вы под verifier получаете взрыв? попробуйте без него.


без него
Re[2]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
От: unintruder  
Дата: 15.07.03 10:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, 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)
От: Valerio Россия linkedin.com/in/boronin
Дата: 15.07.03 11:07
Оценка:
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)
От: unintruder  
Дата: 15.07.03 11:17
Оценка:
Здравствуйте, 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->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = Size;
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);


то все работает, но это же нельзя. Именно по этой причине и пытаюсь обработать 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

DO_BUFFERED_IO ---- Irp->AssociatedIrp.SystemBuffer
DO_DIRECT_IO ---- Irp->MdlAddress

пока больше ничего немогу сказть лучше приведите код
Re[4]: Проблема CompletionRoutine на Irp (IRP_MJ_READ)
От: unintruder  
Дата: 15.07.03 12:24
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>А насчет 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)
От: Valerio Россия linkedin.com/in/boronin
Дата: 18.07.03 07:27
Оценка:
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.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.