How to get the data from my own IRP_MJ_READ in Completion Routine?

Hello all,
I use IoBuildAsynchronousFsdRequest to create a IRP_MJ_READ in my filter driver ,set the completion routiine for it and send it down. I want to get the length ,byteoffset and data returned in the IRP_MJ_READ, so I try to access them in the completion routine,but the length and byteoffset I got are all 0…is that possible to get the data?How?
Thank you~

xxxxx@yahoo.com.cn wrote:

Hello all,
I use IoBuildAsynchronousFsdRequest to create a IRP_MJ_READ in my filter driver ,set the completion routiine for it and send it down. I want to get the length ,byteoffset and data returned in the IRP_MJ_READ, so I try to access them in the completion routine,but the length and byteoffset I got are all 0…is that possible to get the data?How?

Did you set up these values in the request you created?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Yes, I set up them. I can get them just after I create the Irp,but I can’t get them in completion routine…

Show us your code, and let’s see what going on - you must have introduced a bug somewhere…

Anton Bassov

hello~
Actually, I’m doing copy-on-write…
some other questions:

  1. how could I see the changes I made in the volume? I create a temp.txt in my volume, and type in “abcdefg123456”,can I use DebugPrint to print the string in my driver?how?
    2.Everytime I write something in the temp.txt I got a lot IRP_MJ_WRITE,but the ByteOffset I got are different from the offset of the temp.txt I got in WinHex…why?

thank you!
Frente

Here’s the code:

///I create the IRP_MJ_READ in the DispathWrite
NTSTATUS FilterDispatchWrite(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
NTSTATUS orgIrpStatus;
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION pIrpStackLocation;
NTSTATUS status;

KEVENT event;

ULONG Length;
ULONGLONG ByteIndex;
ULONG SectorIndex;
PDEVICE_OBJECT TargetDeviceObject;

PVOID buffer;
IO_STATUS_BLOCK IoStatusBlock;
PIRP shReadIrp;
LARGE_INTEGER StartingOffset;
NTSTATUS readStatus;
PIO_STACK_LOCATION pISL;

deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

pIrpStackLocation = IoGetCurrentIrpStackLocation(Irp);

Length = pIrpStackLocation->Parameters.Write.Length;

ByteIndex = pIrpStackLocation->Parameters.Write.ByteOffset.QuadPart;

////////////////////////////////////////
status = IoAcquireRemoveLock(&deviceExtension->RemoveLock,NULL);
if (!NT_SUCCESS(status)){
DebugPrint((0,“Filter DispatchWrite:IoAcquireRemoveLock Failed.\n”));
}

TargetDeviceObject = deviceExtension->TargetDeviceObject;

StartingOffset.QuadPart = pIrpStackLocation->Parameters.Write.ByteOffset.QuadPart;

if(KeGetCurrentIrql() > PASSIVE_LEVEL){
DebugPrint((0,“Current IRQL > PASSIVE_LEVEL.\n”));
}else{

buffer = ExAllocatePool(NonPagedPool, Length);

KeInitializeEvent(&event,NotificationEvent, FALSE);

shReadIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,TargetDeviceObject,buffer,Length,&StartingOffset,&IoStatusBlock);

if(NULL != shReadIrp){

DebugPrint((0,“shReadIrp created.\n”));

IoSetCompletionRoutine(shReadIrp,FilterReadCompletion,&event,TRUE,FALSE,FALSE);

readStatus = IoCallDriver(TargetDeviceObject, shReadIrp);

if (readStatus == STATUS_PENDING){

KeWaitForSingleObject(&event, Executive, KernelMode,FALSE, NULL);
DebugPrint((0,“shReadIrp completed.\n”));
status = IoStatusBlock.Status;

}
}
}
//////////////////////////////////////////

DebugPrint((0,
“FilterDispatchWrite write:Length::%u,ByteIndex::%u\n”,Length,ByteIndex));

IoSkipCurrentIrpStackLocation(Irp);
orgIrpStatus = IoCallDriver(deviceExtension->TargetDeviceObject, Irp);

IoReleaseRemoveLock(&deviceExtension->RemoveLock, NULL);
DebugPrint((0,“///////////////////////\n”));
return orgIrpStatus;

}

NTSTATUS NsFilterDispatchRead(PDEVICE_OBJECT DeviceObject,PIRP Irp){
PIO_STACK_LOCATION pIrpStackLocation;
PDEVICE_EXTENSION deviceExtension;
deviceExtension =DeviceObject->DeviceExtension;

pIrpStackLocation = IoGetCurrentIrpStackLocation(Irp);

IoCopyCurrentIrpStackLocationToNext(Irp);

DebugPrint((0,
DRIVERNAME " Enter NsFilterDispatchRead Irp = %p Data Length = %I32u Data offset = %I64d.\n",
Irp,
pIrpStackLocation->Parameters.Read.Length,
pIrpStackLocation->Parameters.Read.ByteOffset.QuadPart));

IoSetCompletionRoutine(Irp,NsFilterReadCompletion,NULL,TRUE,TRUE,TRUE);

return IoCallDriver(deviceExtension->TargetDeviceObject,Irp);
}

//IRP_MJ_READ comletion routine
NTSTATUS FilterReadCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PKEVENT pev)
{
PIO_STACK_LOCATION pIrpStackLocation;
ULONG Length;
LARGE_INTEGER StartingOffset;
ULONGLONG ByteIndex;
PVOID pOrgBuf;
ULONG uSrcLength;

if (Irp->PendingReturned){
KeSetEvent(pev, EVENT_INCREMENT, FALSE);

}
pIrpStackLocation = IoGetCurrentIrpStackLocation(Irp);

ByteIndex = pIrpStackLocation->Parameters.Read.ByteOffset.QuadPart;
Length = pIrpStackLocation->Parameters.Read.Length;
DebugPrint((0,“FilterReadCompletion CurrentSL:Length::%u,ByteIndex::%u\n”,Length,ByteIndex));

pOrgBuf = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
uSrcLength = MmGetMdlByteCount(Irp->MdlAddress);

if(pOrgBuf!= NULL){
DebugPrint((0,“pOrgBuf: %x\n”,pOrgBuf));
}else{
DebugPrint((0,“pOrgBuf:Faild.\n”));
}
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;

}

When you allocate an IRP for yourself, it does not have a current io stack location. This means that your call to IoGetCurrentIrpStackLocation is returning garbage. You need to store the relevant info you need in the context parameter. For further info, read

http://blogs.msdn.com/doronh/archive/2006/07/25/677310.aspx

http://blogs.msdn.com/doronh/archive/2007/04/06/your-completion-routine-context-can-be-anything-you-want.aspx

http://blogs.msdn.com/doronh/archive/2007/04/09/problems-with-not-having-a-current-irp-stack-location-part-2.aspx

Finally, I think you are making a fundamental assumption that is incorrect. Your dispatch write routine can be called at IRQL == DISPATCH_LEVEL, which means you cannot wait for i/o to complete synchronously, nor can you call IoBuildXxx().

d

When you use IoBuildXXX() you haven’t got your own stack location in IRP, so that when you call
IoGetCurrentIrpStackLocation() in completion routine, ‘pIrpStackLocation’ points to the middle of nowhere (in fact, it is pretty bizzare that you haven’t yet bluescreened in so far), and ‘DeviceObject’
is NULL (in this context it does not matter - you don’t touch it anyway). If you want to do things the way you do, you have to allocate IRP with IoAllocateIrp() and specify an extra stack location for yourself. By doing so, you will kill 2 birds with one stone - first, you will have your own stack location in IRP, and, second, your code will be able to run at IRQL == DISPATCH_LEVEL (if you remove Wait… part, of course)

Anton Bassov

Thank you ~ I fix it.
But I still confused about other questions:

  1. how could I see the changes I made in the volume? I create a temp.txt in my
    volume, and type in “abcdefg123456”,can I use DebugPrint to print the string in
    my driver?how?
    2.Everytime I write something in the temp.txt I got a lot IRP_MJ_WRITE,but the
    ByteOffset I got are different from the offset of the temp.txt I got in
    WinHex…why?

Thanks in advance

  1. no, not really. You don’t know what the contents of the writes will
    be. Your file’s data is one of many writes your filter will see
  2. this is a file system ;). It uses other structures on the disk to
    maintain state, you are seeing writes against those FS structures

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.com.cn
Sent: Tuesday, April 10, 2007 4:59 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to get the data from my own IRP_MJ_READ in
Completion Routine?

Thank you ~ I fix it.
But I still confused about other questions:

  1. how could I see the changes I made in the volume? I create a temp.txt
    in my
    volume, and type in “abcdefg123456”,can I use DebugPrint to print the
    string in
    my driver?how?
    2.Everytime I write something in the temp.txt I got a lot
    IRP_MJ_WRITE,but the
    ByteOffset I got are different from the offset of the temp.txt I got in
    WinHex…why?

Thanks in advance


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Thanks~
But how could I know I read the right data??Is there any way to check that?

xxxxx@yahoo.com.cn wrote:

But how could I know I read the right data??Is there any way to check that?

Check it against what? You are at the lowest levels here. If something
goes wrong, there’s a serious and likely unrecoverable problem.

If you send a properly formatted IRP_MJ_READ request to a driver that
handles read requests, you will either get back a buffer of data or an
error code. You can’t do much better than that.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

If I use IoBuildSynchronousFsdRequest(IRP_MJ_READ,TargetDeviceObject,buffer,Length,&StartingOffset,&event,&IoStatusBlock) at PASSIVE_LEVEL, and I got success in IoStatusBlock, then I got the right data in buffer and there’s no need to check it.
Is that right?

xxxxx@yahoo.com.cn wrote:

If I use IoBuildSynchronousFsdRequest(IRP_MJ_READ,TargetDeviceObject,buffer,Length,&StartingOffset,&event,&IoStatusBlock) at PASSIVE_LEVEL, and I got success in IoStatusBlock, then I got the right data in buffer and there’s no need to check it.
Is that right?

What would you check? You might want to make sure that the Information
field in the IoStatusBlock has the right number of bytes, but beyond
that, what could you do?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Ok.I read the origin data before write. I just want to know I did it right, got the right data.
Is there no need to do this?

xxxxx@yahoo.com.cn wrote:

Ok.I read the origin data before write. I just want to know I did it right, got the right data.
Is there no need to do this?

Maybe one or twice during debugging, just to prove that your algorithm
is right, but I wouldn’t think so after that.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.