Easy question on IRP_MJ_READ

I know this is simple, but …

I am writing a simple kernel driver from scratch for self education
purposes. The driver declares entry points for IRP_MJ_CREATE, *_CLOSE, and
*_READ.

In response to a READ it fills the user buffer with landfill and returns
STATUS_SUCCESS. That’s it. I use buffered IO. The calls into the functions
look fine, I get nice values for my buffer and buffer size (StackLoc->
Parameters.Read.Length) going in to my driver code.

I am discovering in my user code that while ReadFile() returns TRUE, the
char count is zero, and the buffer is untouched. Obviously I need to ‘tell’
the IO Manager how many bytes I wrote into that buffer - but how do I do
that?

Where do I stuff that number??

Here is a code fragment from the read routine…

pStackLoc = IoGetCurrentIrpStackLocation(Irp);

llOffset = pStackLoc->Parameters.Read.ByteOffset.QuadPart;
p = pStart = (UCHAR*)Irp->AssociatedIrp.SystemBuffer + llOffset;

for(idx = 0; idx < pStackLoc->Parameters.Read.Length; ++idx)
*p = 0xef;

Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;

You have to set Irp->IoStatus.Information to the number of bytes written to the buffer (before calling IoComleteRequest())

d

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Eric Fowler
Sent: Wednesday, December 06, 2006 1:40 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Easy question on IRP_MJ_READ

I know this is simple, but …

I am writing a simple kernel driver from scratch for self education purposes. The driver declares entry points for IRP_MJ_CREATE, *_CLOSE, and *_READ.

In response to a READ it fills the user? buffer with landfill and returns STATUS_SUCCESS. That’s it. I use buffered IO. The calls into the functions look fine, I get nice values for my buffer and buffer size (StackLoc-> Parameters.Read.Length) going in to my driver code.

I am discovering in my user code that while ReadFile() returns TRUE, the char count is zero, and the buffer is untouched. Obviously I need to ‘tell’ the IO Manager how many bytes I wrote into that buffer - but how do I do that?

Where do I stuff that number??

Here is a code fragment from the read routine…

??? pStackLoc = IoGetCurrentIrpStackLocation(Irp);

??? llOffset = pStackLoc->Parameters.Read.ByteOffset.QuadPart ;
??? p = pStart = (UCHAR*)Irp->AssociatedIrp.SystemBuffer + llOffset;
???
??? for(idx = 0; idx < pStackLoc->Parameters.Read.Length; ++idx)
??? ??? *p = 0xef;

??? Irp->IoStatus.Status = STATUS_SUCCESS;
??? IoCompleteRequest(Irp, IO_NO_INCREMENT);
??? return STATUS_SUCCESS;

— 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

You need to set Irp->IoStatus.Information to indicate the number of
bytes of data you’re returning to the caller. The I/O manager uses this
value to determine how many bytes of data it can safely (i.e. without
exposing old kernel data you didn’t overwrite) copy back into usermode.

Make sure this value is <= the size of the buffer you were given. The
i/o manager treats it as gospel and you can easily get it to read past
the end of the kernel mode buffer which, if you’re lucky, will cause an
immediate crash so you can debug it. If you’re not luck it will fail at
some time in the future & cause a major pain.

-p

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Eric Fowler
Sent: Wednesday, December 06, 2006 1:40 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Easy question on IRP_MJ_READ

I know this is simple, but …

I am writing a simple kernel driver from scratch for self education
purposes. The driver declares entry points for IRP_MJ_CREATE, *_CLOSE,
and *_READ.

In response to a READ it fills the user buffer with landfill and
returns STATUS_SUCCESS. That’s it. I use buffered IO. The calls into the
functions look fine, I get nice values for my buffer and buffer size
(StackLoc-> Parameters.Read.Length) going in to my driver code.

I am discovering in my user code that while ReadFile() returns TRUE, the
char count is zero, and the buffer is untouched. Obviously I need to
‘tell’ the IO Manager how many bytes I wrote into that buffer - but how
do I do that?

Where do I stuff that number??

Here is a code fragment from the read routine…

pStackLoc = IoGetCurrentIrpStackLocation(Irp);

llOffset = pStackLoc->Parameters.Read.ByteOffset.QuadPart ;
p = pStart = (UCHAR*)Irp->AssociatedIrp.SystemBuffer + llOffset;

for(idx = 0; idx < pStackLoc->Parameters.Read.Length; ++idx)
*p = 0xef;

Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;

— 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

> I am discovering in my user code that while ReadFile() returns TRUE, the

char count is zero, and the buffer is untouched. Obviously I need to ‘tell’
the IO Manager how many bytes I wrote into that buffer - but how do I do
that?

Yes.

Irp->IoStatus.Information = NumberOfBytesActuallyRead;

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com