Hi, Takashi:
NTSTATUS NTAPI
MyGetFileSize(
IN PDEVICE_OBJECT pDeviceObject,
IN PFILE_OBJECT pFileObject,
OUT PLARGE_INTEGER pFileSize)
{
// Rolling my own Irp.
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
IoSetCompletionRoutine(pIRP, MyCompleteRoutine,
NULL, TRUE, TRUE, TRUE);
ntResult = IoCallDriver(pDeviceObject, pIRP);
if(ntResult == STATUS_PENDING){
ntResult = KeWaitForSingleObject(
&Event, Suspended, KernelMode, FALSE, 0);
// this function never returns because my completion
// routine is never called.
}else{
ntResult = KeWaitForSingleObject(
&Event, Executive, KernelMode, TRUE, 0);
I don´t know why you call KeWaitForSingleObject even when IoCallDriver does
not return STATUS_PENDING. This should be necessary only when STATUS_PENDING
is returned.
NTSTATUS MyCompleteRoutine(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIRP,
IN PVOID pContext)
{
if(pIRP->PendingReturned){
IoMarkIrpPending(pIRP);
}
I´m almost sure this is incorrect. I had the same problem and this caused a
page fault. Maybe in your case the effect is that your completion routine
seems to be never called.
The problem is the following: since you are rolling your own IRP, I assume
you allocate it and initialize it, so, that means your device is the first
one in the stack. IoMarkIrpPending seems to access the PREVIOUS stack
location, and since yours is the first one, just imagine what a mess could
result from this.
And just another remark: remember to pass the IRP to the device you´re
attached to, never to other device such as the one taken from
FileObject->DeviceObject, since then that IRP would incur in unneeded
overhead and you could be facing reentrancy problems (that IRP will arrive
to your driver).
I use the following code successfully to retrieve the file size from a file
(using a standard info query):
/*=======================================================================*/
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
}
/*=======================================================================*/
static BOOLEAN irpGetInfo(
PDEVICE_OBJECT hookedDevice,
PFILE_OBJECT fileObject,
PVOID buffer,
ULONG bufferLength,
FILE_INFORMATION_CLASS fileInfoClass
)
{
PIRP irp;
PIO_STACK_LOCATION irpSp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
irp = IoAllocateIrp(hookedDevice->StackSize, FALSE);
KeInitializeEvent(&event, NotificationEvent, FALSE);
RtlZeroMemory(buffer, bufferLength);
irp->AssociatedIrp.SystemBuffer = buffer;
irp->UserEvent = &event;
irp->UserIosb = &ioStatus;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject = fileObject;
irp->RequestorMode = KernelMode;
irp->Flags = IRP_NOCACHE;
irpSp = IoGetNextIrpStackLocation(irp);
irpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION;
irpSp->MinorFunction = 0;
irpSp->DeviceObject = hookedDevice;
irpSp->FileObject = fileObject;
irpSp->Parameters.QueryFile.Length = bufferLength;
irpSp->Parameters.QueryFile.FileInformationClass = fileInfoClass;
IoSetCompletionRoutine(irp, &irpCompletion, 0, TRUE, TRUE, TRUE);
IoCallDriver(hookedDevice, irp);
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
return NT_SUCCESS(ioStatus.Status);
}
/*=======================================================================*/
BOOLEAN irpGetStandardInfo(
PDEVICE_OBJECT hookedDevice,
PFILE_OBJECT fileObject,
PFILE_STANDARD_INFORMATION standardInfo
)
{
DbgPrint((“direct IRP get standard information\n”));
return irpGetInfo(
hookedDevice,
fileObject,
standardInfo,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation
);
}
/*=======================================================================*/
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