I’m writing a lower filter for cdrom in order to make a crypted disc,
you might think it’s a bad idea, but anyway that’s not the point.
when i start filtering SCSIO_READ(10) and made a try to split a read operation into several stages, i was confused by IoBuildPartialMdl.
the following is what i have done. sorry the codes were not in my hand so i wrote the following by memory.
It’s direct IO and run at IRQL_DISPATCH_LEVEL.
when it read more than 1 block, i tried to split into serval operation.it’s seemed to be a paging I/O. srb->DataBuffer was NULL, and MdlFlags was MDL_MAPPED_TO_SYSTEM_VA | MDL_PAGES_LOCKED | MDL_IO_PAGE_READ.
the current process is explorer, which was trying to read a PE file to display its icon.
I allocated a MDL and build it.
Mdl = IoAllocateMdl (irp->MdlAddress,
Mdl,
MmGetMdlVirtualAddress(irp->MdlAddress), // 0
MmGetMdlByteCount(irp->MdlAddree), // 0x1000
NULL);
IoBuildPartialMdl (irp->MdlAddress,
Mdl,
MmGetMdlVirtualAddress(irp->MdlAddress),
devExt->blockSize // 0x800
);
then save irp->MdlAddress and replace it with the partial mdl, modify srb->DataTransferLength and srb->Cdb to read only 1 block, passed it to the lower device.
In completion, i found it worked (by checking the result with MmGetSystemAddressForMdlSafe),
and then :
MmPrepareMdlForReuse (devExt->Mdl); //same as the current irp->MdlAddress, the partial one
IoBuildPartialMdl (devExt->originalMdl, // if use current irp->MdlAddress, i got same result
devExt->Mdl,
(PUCHAR)MmGetMdlVirtualAddress(devExt->originalMdl) + counter * devExt->blockSize,
devExt->blockSize
);
i modified srb->Cdb to increment LBA and call lower driver again (return
STATUS_MORE_PROCESSING_REQUIRED). if it’s the last block i replace irp->MdlAddress
back with the original one and return STATUS_CONTINUE_COMPLETION.
Now this is my problem.
the read operation of the 2nd block seemed to succeeded since status is ok, but this time the data is read out and copied into the last same address where the 1st block of data resided (mean it occupied the 1st block of data), the buffer+0x800 held nothing!
IoBuildPartialMdl didn’t work? if call MmGetSystemAddressForMdlSafe(irp->MdlAddress) here, it did point to buffer+0x800.
there’s something unknown force it to always copy data into the beginning of buffer?
i made anther try, allocate a NonPagedPool, MmBuildMdlForNonPagedPool and replaced
irp->MdlAddress directly to test it, this time i got BSOD (even the break point in ompletion entry not hit), IRQL_NOT_LESS_OR_EQUAL with a invalid address, it seemed to have something with DMA (some function name like Scatter/Gather). I know nothing about DMA.
What should i do if i hope to decrypt data block by block in completion? maybe i can process all the data only once and never split the read operation?
thanks for any help.