Hi, devs, I need some help:
I´m writing a FSF which monitors each IRP_MJ_CREATE, and then checks if the
file just opened is a special type of file.
For this purpose, I pass the IRP_MJ_CREATE down to the attached device and
wait for its completion. Then I do the file check. For this purpose I need
to do some read operations, which I perform building my own read IRPs and
passing them down to the underlying driver.
The scheme seemed to work very well, and is being tested in a NT 4.0 SP6
checked platform.
But today, just to stress my FSF a little bit, I tried a simple program that
did the following operation 1000 times: CreateFile, GetFileSize,
CloseHandle. That´s it.
Well, after one hundred or so of iterations, I get the following assertion
error when passing down the read IRP (using IoCallDriver):
*** assertion failed: Pfn1->u3.e2.ReferenceCount < MmReferenceCountCheck2
*** source file: w:\nt\private\ntos\mm\up..\iosup.c, line 456
The meaning seems rather evident: there is a reference count going out of
bounds, but I gave no clue to which objects it refers to.
Since this happens only after about 100 iterations
(open/get_file_size/close):
It seems not to be the IRP itself, since a different one is created and
freed for each read operation.
It seems not to be the FileObject, since it is a different one for each
OPEN/GETFILESIZE/CLOSE operation.
Any clues / directions ?. I would appreciate them very much.
Note: I don´t use IoBuildSynchronousFsdRequest, and I think it was because I
had initialy some problems with it and got this approach working rather
fast. However, since I cook the whole read IRP myself, perhaps I´m
forgetting some obscure but important field… I attach my code at the end
of the message just in case some brave dev wants to have a look to it
Thanks. Nacho.
static NTSTATUS irpCompletion(
PDEVICE_OBJECT deviceObject,
PIRP irp,
PVOID context
)
{
*irp->UserIosb = irp->IoStatus; // Copy status information to
// the user
KeSetEvent(irp->UserEvent, 0, FALSE); // Signal event
IoFreeIrp(irp); // Free IRP
return STATUS_MORE_PROCESSING_REQUIRED; // Tell the I/O manager to stop
}
BOOLEAN irpRead(
PDEVICE_OBJECT hookedDevice,
PFILE_OBJECT fileObject,
PLARGE_INTEGER offset,
PVOID buffer,
ULONG length
)
{
PIRP irp;
PIO_STACK_LOCATION irpSp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
irp = IoAllocateIrp(hookedDevice->StackSize, FALSE);
if (irp == NULL) {
return FALSE;
}
KeInitializeEvent(&event, NotificationEvent, FALSE);
// Read uses neither I/O, so we must pass the buffer in UserBuffer
irp->UserBuffer = buffer;
irp->UserEvent = &event;
irp->UserIosb = &ioStatus;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject = fileObject;
irp->RequestorMode = KernelMode;
irp->Flags = IRP_READ_OPERATION | IRP_NOCACHE;
irpSp = IoGetNextIrpStackLocation(irp);
irpSp->MajorFunction = IRP_MJ_READ;
irpSp->MinorFunction = 0;
irpSp->DeviceObject = hookedDevice;
irpSp->FileObject = fileObject;
irpSp->Parameters.Read.Length = length;
irpSp->Parameters.Read.Key = 0;
irpSp->Parameters.Read.ByteOffset = *offset;
IoSetCompletionRoutine(irp, irpCompletion, 0, TRUE, TRUE, TRUE);
DbgPrint((“??? About to call IoCallDriver for direct IRP read\n”));
IoCallDriver(hookedDevice, irp);
DbgPrint((“??? Just called IoCallDriver for direct IRP read\n”));
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);
return NT_SUCCESS(ioStatus.Status) && // Success only if we could
ioStatus.Information == length; // read all requested data
}
You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com