In my initial pass I noticed at least one glaring error (that probably
doesn’t cause it to crash):
Do not assign one stack location to the next. Use
IoCopyCurrentIrpStackLocationToNext.
And then back to your original question:
It is OK to decrypt in place. But your code assumes Irp->UserBuffer, which
is not necessarily valid, particularly for paging I/O operations. Instead,
you should look to see if Irp->MdlAddress is already set. If it is, use the
MDL, not the user buffer.
The important point here is to keep in mind that at the point your filter
gets a paging I/O IRP, that MDL is the only thing that really matters - it
describes the physical memory that will EVENTUALLY be mapped. But it is not
mapped yet (otherwise, some process might try to access it.) So you need to
focus on using the MDL to satisfy the operation.
Does that make more sense?
Regards,
Tony
Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com
-----Original Message-----
From: Bill [mailto:xxxxx@endwell.net]
Sent: Thursday, November 21, 2002 9:29 AM
To: File Systems Developers
Subject: [ntfsd] RE: IRP_PAGING_IO problem
Thanks again for answering. I wasn’t even thinking about MJ_WRITE or
fabricating my own IRPs yet, so your comment didn’t click. Now I
understand. For the moment, this is a read-only experiment.
The problem I see if I try to handle IPR_PAGING_IO read requests is: 1)
decryption failure and 2) a subsequent BugCheck some seconds later,
*seemingly* unrelated to whjat just happened - no stack trace leads back
to my driver. Here are snippets of my read and completion routines.
Note that the BugCheck occurs even if I do not attempt to Decrypt
(commented out). If I intentionally ignore the PAGING_IO case, either by
not setting the IoCompletionRoutine, or by skipping most of the processing
within same, my decryption works OK (for most files) and does not trap.
The driver exposes itself as, in this case, NEITHER_IO, same as the FSD
below.
IRP_MJ_READ:
.
.
.
readContext.offset = fileObject->CurrentByteOffset.LowPart;
if (!(Irp->Flags & IRP_PAGING_IO)) {
readContext.pMdl = IoAllocateMdl
(
Irp->UserBuffer,
currentIrpStack->Parameters.Read.Length,
FALSE, FALSE, NULL
);
__try {
MmProbeAndLockPages( readContext.pMdl, KernelMode, IoModifyAccess );
}
__except( EXCEPTION_EXECUTE_HANDLER) {
IoFreeMdl( readContext.pMdl );
return GetExceptionCode();
}
}
else {
// cannot Probe and Lock on a PAGING_IO request, just pass the MDL
DbgPrint( “PAGING_IO read”);
readContext.pMdl = Irp->MdlAddress;
}
// Before calling the FSD driver with the request, set a completion
// routine where we can do our thang.
IoSetCompletionRoutine
(
Irp,
PFFReadCompletionRoutine,
&readContext,
TRUE,
TRUE,
TRUE
);
*nextIrpStack = *currentIrpStack;
lowerStatus = IoCallDriver( hookExt->FileSystem, Irp );
return lowerStatus;
My PFFReadCompletionRoutine:
.
.
.
if (Irp->IoStatus.Status == STATUS_SUCCESS) {
if (len > 0) { // only Decrypt if we read anything
buffer = MmGetSystemAddressForMdl( pReadContext->pMdl );
DbgPrint( “Decrypt %d bytes at address %08x from offset %08x”, len,
buffer, pReadContext->offset );
DbgPrint( “buffer address: %08x, user buffer address: %08x”, buffer,
Irp->UserBuffer );
// Decrypt( buffer, len, pReadContext->offset );
}
else {
DbgPrint( “NOT decrypting: non-positive length from FSD” );
}
}
else {
DbgPrint( “NOT decrypting: non-zero rc from FSD: %08x”,
Irp->IoStatus.Status );
}
if (Irp->Flags & IRP_PAGING_IO) {
;
}
else {
MmUnlockPages( pReadContext->pMdl );
IoFreeMdl( pReadContext->pMdl );
}
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
return( STATUS_SUCCESS );
I’m not exactly a newbie to device drivers, having written them for AIX,
Netware, OS/2 and Windows 9x/NT, but this is my first crack at something
like a filter driver.
I’m also pretty sure this is something simple I’m missing (still waiting
on
my IFS kit to come…)
If *you* set Irp->MdlAddress, *you* are responsible for setting
Irp->UserBuffer. If you do not do this, it will lead to problems.
The confusing part is that Irp->UserBuffer isn’t necessarily VALID - it
just
has to be THE SAME. This is because it is used as an index parameter when
breaking the MDL into partial MDLs (you can see this in
FatMultipleAsyncWrite as I recall.)
Regards,
Tony
Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com
You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to %%email.unsub%%