The line:
return IoCallDriver( hookExt->FileSystem, Irp );
is problematic. If you wish to continue processing the IRP in a worker
routine, you must either (a) mark the IRP as pending (in your dispatch
routine before IoCallDriver or in your completion routine before you enqueue
the IRP) and return STATUS_PENDING from your dispatch entry point; or (b)
block and wait for the worker thread to complete the IRP. Otherwise, I/O
completion processing will occur out-of-order (because there are two parts,
a context independent part, and a context dependent part.)
This is just one of the classic problems in file system filter drivers.
Further, your project (an encryption filter) is typically one of the most
challenging filters one can build. I’m not trying to discourage you. Well,
OK, I am. I always try to discourage everyone from building a file system
filter driver if they can avoid doing so.
I hope this helps.
Regards,
Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com
-----Original Message-----
From: xxxxx@novosoft.ru [mailto:xxxxx@novosoft.ru]
Sent: Monday, July 10, 2000 4:13 PM
To: File Systems Developers
Subject: [ntfsd] Help!!! Crash due read request to the underlayered
driver on IRP_MJ_CREATE!
Hello, all!
We are writing a filter driver and are having problems (like many before by
the looks of it ;)) We are trying to read from file in a completion routine
when we receive IRP_MJ_CREATE requests, so that we can identify files we
need to decrypt. (we have a header on our files)
In the completion routine for the create we queue a work item to try and do
the read from and return STATUS_MORE_PROCESSING_REQUIRED.
In the worker function we use IoBuildSynchronousFsdRequest to create an IRP
for the read and send it on.
This all should works fine in almost every circumstance, but in my case I’m
always crashed! Help!!! Does anyone have any ideas?
We have pasted the offending chunk of code below.
Thanks for any assitance…
//Here we hook all file I/O IRPs
NTSTATUS EfsHookRoutine( PDEVICE_OBJECT HookDevice, IN PIRP Irp )
{
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject;
PHOOK_EXTENSION hookExt;
//
// Extract the file object from the IRP
//
FileObject = currentIrpStack->FileObject;
//
// Point at the device extension, which contains information on which
// file system this IRP is headed for
//
hookExt = HookDevice->DeviceExtension;
//IRP_MJ_CREATE request: let’s try to read file after completion of
it
if (currentIrpStack->MajorFunction==IRP_MJ_CREATE &&
!(currentIrpStack->Parameters.Create.Options & FILE_DIRECTORY_FILE))
{
IoSetCompletionRoutine(Irp,EfsHookCreateDone,0,TRUE,TRUE,TRUE );
}
else
{
//all other requests here
IoSetCompletionRoutine(Irp,EfsHookDone,0,TRUE,TRUE,TRUE );
}
//
// Return the results of the call to the caller
//
return IoCallDriver( hookExt->FileSystem, Irp );
}
NTSTATUS EfsHookCreateDone(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN
PVOID Context )
{
PIO_STACK_LOCATION IrpSp;
PEFS_WORK efsWorkContext;
int seq = (int)Context;
KIRQL oldirql;
// A request completed - look at the result
IrpSp = IoGetCurrentIrpStackLocation( Irp );
// Queue off to a worker thread if we have to (now I’m always do this)
//if( KeGetCurrentIrql() == DISPATCH_LEVEL )
{
efsWorkContext = ExAllocatePool( NonPagedPool,
sizeof(EFS_WORK));
if( efsWorkContext )
{
PHOOK_EXTENSION
hookExt=DeviceObject->DeviceExtension;
efsWorkContext->Irp =Irp;
//pass hooked underlayed device object to the work
item
efsWorkContext->DeviceObject=hookExt->FileSystem;
efsWorkContext->Sequence =seq;
efsWorkContext->TimeResult =timeResult;
ExInitializeWorkItem( &efsWorkContext->WorkItem,
EfsHookCreateDoneWork, efsWorkContext );
ExQueueWorkItem( &efsWorkContext->WorkItem, CriticalWorkQueue );
}
}
// Now we have to mark Irp as pending if necessary
if( Irp->PendingReturned ) IoMarkIrpPending( Irp );
return STATUS_MORE_PROCESSING_REQUIRED;
}
// Running in the context of a worker thread
// using ExInitializeWorkItem &ExQueueWorkItem
VOID EfsHookCreateDoneWork( PEFS_WORK pContext )
{
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
PCHAR Buffer;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER ByteOffset;
LARGE_INTEGER OrigByteOffset;
// Get the Previous filtered device object
DeviceObject=pContext->DeviceObject;
FileObject=IoGetCurrentIrpStackLocation(pContext->Irp)->FileObject;
// No point in continuing if there is no FileObject
if (FileObject)
{
// Allocate memory for our 512-bytes Buffer
Buffer = ExAllocatePool( NonPagedPool, 512 );
if (Buffer)
{
ByteOffset.QuadPart = 0;
// Store the original byte offset
OrigByteOffset = FileObject->CurrentByteOffset;
//ALWAYS CRASH HERE (in DbgReadFile, after
ioCallDriver)!!!
DbgReadFile( pContext->Irp,DeviceObject, FileObject,
&ByteOffset, 512, Buffer, &IoStatusBlock );
// Restore the original byte offset
FileObject->CurrentByteOffset = OrigByteOffset;
if (NT_SUCCESS(IoStatusBlock.Status))
{
}
else
{
}
// Free our read buffer
ExFreePool( Buffer );
}
}
//Complete the Create Request
IoCompleteRequest( pContext->Irp, IO_NO_INCREMENT );
// Free the create context data
ExFreePool( pContext );
}
VOID DbgReadFile( PIRP pIrp, PDEVICE_OBJECT DeviceObject, PFILE_OBJECT
FileObject, PLARGE_INTEGER Offset, ULONG Length, PCHAR Buffer,
PIO_STATUS_BLOCK IoStatusBlock )
{
KEVENT kEvent;
PIRP pReadIrp;
NTSTATUS ntStatus;
// Initialise an event to wait for after calling the previous driver
KeInitializeEvent( &kEvent, NotificationEvent, FALSE );
// Build an Irp for the read
pReadIrp=(IRP_MJ_READ,DeviceObject,Buffer,Length,Offset,&kEvent,IoStatusBloc
k );
if (pReadIrp)
{
PIO_STACK_LOCATION pReadStack = IoGetNextIrpStackLocation(
pReadIrp );
// Caching? no thank you maam!
pReadIrp->Flags = IRP_NOCACHE | IRP_READ_OPERATION;
pReadIrp->Tail.Overlay.Thread = pIrp->Tail.Overlay.Thread;
pReadIrp->RequestorMode = KernelMode;
// We need a FileObject to identify the file we are reading
pReadStack->FileObject = FileObject;
pReadStack->DeviceObject = DeviceObject;
// Call on to the previous driver
ntStatus = IoCallDriver( DeviceObject, pReadIrp );
if (ntStatus == STATUS_PENDING)
{
// Wait for the Irp to complete if it is pending
KeWaitForSingleObject( &kEvent, Executive,
KernelMode, FALSE, NULL );
}
else IoStatusBlock->Status = ntStatus;
}
else
{
IoStatusBlock->Status=STATUS_INSUFFICIENT_RESOURCES;
IoStatusBlock->Information=0;
}
}
Code looks like without any errors, but in real life it crashes…
Why? If you notice some criminal, let me know, please!
Kind Regards and thanks in advance
Valery A. Boronin,
System Software Engineer, Novosoft
http://www.novosoft.ru
You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)