Split an IO request

How do I split an IO request in KMDF? In my test driver, when my app reads 8 sectors starting at 0, the first sector will come from a file and the rest from a block device. Here is my code to handle the Read operation (assume all calls return successfully).

WDF_REQUEST_PARAMETERS_INIT(&parameters);
WdfRequestGetParameters(Request, &parameters);

status = WdfRequestRetrieveOutputMemory(Request, &hMemory);

fileOffset.QuadPart = parameters.Parameters.Read.DeviceOffset;
if(fileOffset.QuadPart >= 0 && fileOffset.QuadPart <= 512)
{
curLen = (size_t) (512 - fileOffset.QuadPart + 1);
buf = (PUCHAR) ExAllocatePoolWithTag(NonPagedPool, curLen, MYTESTDEV_TAG);

// Read from file
status = ZwReadFile(pDevContext->fileHandle,// File handle
NULL,// handle to event obj for completion
NULL,// reserved
NULL,// reserved
&ioStatusBlock,// Completion status
buf,// buf for read data
curLen,// bytes to read
&fileOffset,// read offset
NULL);// key, should be NULL

status = WdfMemoryCopyFromBuffer(hMemory, 0, buf, curLen);
status = WdfMemoryCopyFromBuffer(hMemory,

/* I tried to use the same hMemory object to read from the block device. And it doesn’t work */

totalLen = parameters.Parameters.Read.Length;
if(totalLen > curLen)
{
memOffset.BufferOffset = curLen;
memOffset.BufferLength = totalLen - curLen;
// Use an offset to skip the part that already read
WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memDescriptor, hMemory, &memOffset);

byteOffset = parameters.Parameters.Read.DeviceOffset + curLen;

// Read from block dev
status = WdfIoTargetSendReadSynchronously(pDevContext->ioTarget,
NULL,
&memDescriptor,
&byteOffset,
NULL,
&information);

information += (ULONG_PTR) curLen;
}
}
// Complete the request here.

I got an Assertion @ WdfIoTargetSendReadSynchronously

*** Assertion failed: pBuf != NULL
*** Source File: d:\vistartm\drivers\wdf\kmdf\src\support\fxrequestbuffer.cpp, line 369

Why can I reuse the hMem with an offset? TIA.

Chu Bun

!wdflogdump should give you more information about the assert.

To use the hMemory’s buffer in your ZwReadFile call WdfMemoryGetBuffer to get the underlying C pointer and you can pass it directly. OR, you could create a remote io target intead of using fileHandle (open a target by name) and then you can use the WDFMEMORY directly in the read call.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.com
Sent: Tuesday, December 16, 2008 5:23 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Split an IO request

How do I split an IO request in KMDF? In my test driver, when my app reads 8 sectors starting at 0, the first sector will come from a file and the rest from a block device. Here is my code to handle the Read operation (assume all calls return successfully).

WDF_REQUEST_PARAMETERS_INIT(&parameters);
WdfRequestGetParameters(Request, &parameters);

status = WdfRequestRetrieveOutputMemory(Request, &hMemory);

fileOffset.QuadPart = parameters.Parameters.Read.DeviceOffset;
if(fileOffset.QuadPart >= 0 && fileOffset.QuadPart <= 512)
{
curLen = (size_t) (512 - fileOffset.QuadPart + 1);
buf = (PUCHAR) ExAllocatePoolWithTag(NonPagedPool, curLen, MYTESTDEV_TAG);

// Read from file
status = ZwReadFile(pDevContext->fileHandle,// File handle
NULL,// handle to event obj for completion
NULL,// reserved
NULL,// reserved
&ioStatusBlock,// Completion status
buf,// buf for read data
curLen,// bytes to read
&fileOffset,// read offset
NULL);// key, should be NULL

status = WdfMemoryCopyFromBuffer(hMemory, 0, buf, curLen);
status = WdfMemoryCopyFromBuffer(hMemory,

/* I tried to use the same hMemory object to read from the block device. And it doesn’t work */

totalLen = parameters.Parameters.Read.Length;
if(totalLen > curLen)
{
memOffset.BufferOffset = curLen;
memOffset.BufferLength = totalLen - curLen;
// Use an offset to skip the part that already read
WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memDescriptor, hMemory, &memOffset);

byteOffset = parameters.Parameters.Read.DeviceOffset + curLen;

// Read from block dev
status = WdfIoTargetSendReadSynchronously(pDevContext->ioTarget,
NULL,
&memDescriptor,
&byteOffset,
NULL,
&information);

information += (ULONG_PTR) curLen;
}
}
// Complete the request here.

I got an Assertion @ WdfIoTargetSendReadSynchronously

Assertion failed: pBuf != NULL
Source File: d:\vistartm\drivers\wdf\kmdf\src\support\fxrequestbuffer.cpp, line 369

Why can I reuse the hMem with an offset? TIA.

Chu Bun


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

I couldn’t run wdflogdump.
!wdflogdump MyTestDev
No export wdflogdump found
I use WDK 6000 (KMDF 1.5) on an AMD 64 computer.

Anyway, reading from the file is OK. It’s the second part of the read that has raise the assertion. In the returned buf, the first sector from the file has correct data, but the remaining 7 sectors read from the block device show all 0’s.

I tried WdfMemoryGetBuffer before but also ran into some assertions. but I’ll try again.

!wdfkd.wdflogdump

d

Sent from my phone with no t9, all spilling mistakes are not intentional.

-----Original Message-----
From: xxxxx@yahoo.com
Sent: Wednesday, December 17, 2008 9:29 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Split an IO request

I couldn’t run wdflogdump.
!wdflogdump MyTestDev
No export wdflogdump found
I use WDK 6000 (KMDF 1.5) on an AMD 64 computer.

Anyway, reading from the file is OK. It’s the second part of the read that has raise the assertion. In the returned buf, the first sector from the file has correct data, but the remaining 7 sectors read from the block device show all 0’s.

I tried WdfMemoryGetBuffer before but also ran into some assertions. but I’ll try again.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

I loaded the dll and tmf file, and run wdflogdump, but I couldn’t anything related to the buffer assertion.

kd> !wdflogdump MyTestDev
Trace searchpath is:

Trace format prefix is: %7!u!: %!FUNC! -
TMF file used for formatting IFR log is: C:\WINDDK\6000\tools\tracing\amd64\wdf01005.tmf
Log at 83050000
Gather log: Please wait, this may take a moment (reading 4032 bytes).
% read so far … 10, 20, 100
There are 21 log entries
— start of log —
1: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering PnP State WdfDevStatePnpInit from WdfDevStatePnpObjectCreated
2: FxPkgPnp::Dispatch - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258, IRP_MJ_PNP, 0x00000000(IRP_MN_START_DEVICE) IRP 0x8304D678
3: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering PnP State WdfDevStatePnpInitStarting from WdfDevStatePnpInit
4: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering PnP State WdfDevStatePnpHardwareAvailable from WdfDevStatePnpInitStarting
5: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering power policy state WdfDevStatePwrPolStarting from WdfDevStatePwrPolObjectCreated
6: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering power idle state FxIdleStarted from FxIdleStopped
7: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering Power State WdfDevStatePowerStartingCheckDeviceType from WdfDevStatePowerObjectCreated
8: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering Power State WdfDevStatePowerD0Starting from WdfDevStatePowerStartingCheckDeviceType
9: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering Power State WdfDevStatePowerD0StartingConnectInterrupt from WdfDevStatePowerD0Starting
10: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering Power State WdfDevStatePowerD0StartingDmaEnable from WdfDevStatePowerD0StartingConnectInterrupt
11: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering Power State WdfDevStatePowerD0StartingStartSelfManagedIo from WdfDevStatePowerD0StartingDmaEnable
12: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering power idle state FxIdleStartedPowerUp from FxIdleStarted
13: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering power idle state FxIdleDisabled from FxIdleStartedPowerUp
14: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering Power State WdfDevStatePowerDecideD0State from WdfDevStatePowerD0StartingStartSelfManagedIo
15: FxPkgPnp::PowerEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering Power State WdfDevStatePowerD0 from WdfDevStatePowerDecideD0State
16: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering power policy state WdfDevStatePwrPolStartingSucceeded from WdfDevStatePwrPolStarting
17: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering power policy state WdfDevStatePwrPolStartingDecideS0Wake from WdfDevStatePwrPolStartingSucceeded
18: FxPkgPnp::PowerPolicyEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering power policy state WdfDevStatePwrPolStarted from WdfDevStatePwrPolStartingDecideS0Wake
19: FxPowerIdleMachine::ProcessEventLocked - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering power idle state FxIdleDisabled from FxIdleDisabled
20: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering PnP State WdfDevStatePnpEnableInterfaces from WdfDevStatePnpHardwareAvailable
21: FxPkgPnp::PnpEnterNewState - WDFDEVICE 0x7CDCB240 !devobj 0x8329A258 entering PnP State WdfDevStatePnpStarted from WdfDevStatePnpEnableInterfaces
---- end of log ----

kd> !devobj 0x8329A258
Device object (8329a258) is for:
MyTestDev \Driver\MyTestDev DriverObject 83258ca8
Current Irp 00000000 RefCount 2 Type 00000007 Flags 00002050
Vpb 8322f618 Dacl e17ae6ac DevExt 83234f80 DevObjExt 8329a368 Dope 83261ce8
ExtensionFlags (0000000000)
AttachedTo (Lower) 8339ab88 \Driver\PnpManager
Device queue is not busy.

kd> !IRP 0x8304D678
Irp is active with 3 stacks 4 is current (= 0x8304d754)
No Mdl: No System Buffer: Thread 00000000: Irp is completed. Pending has been returned
cmd flg cl Device File Completion-Context
[0, 0] 0 0 00000000 00000000 00000000-00000000

Args: 00000000 00000000 00000000 00000000
[0, 0] 0 0 00000000 00000000 00000000-00000000

Args: 00000000 00000000 00000000 00000000
[f, 0] 0 0 82f98038 00000000 f6a862bc-832350f0
\Driver\usbuhci usbhub!USBH_ChangeIndication
Args: 00000000 00000000 00000000 00000000

xxxxx@yahoo.com wrote:

I loaded the dll and tmf file, and run wdflogdump, but I couldn’t anything related to the buffer assertion.

kd> !wdflogdump MyTestDev
Trace searchpath is:

Trace format prefix is: %7!u!: %!FUNC! -
TMF file used for formatting IFR log is: C:\WINDDK\6000\tools\tracing\amd64\wdf01005.tmf

You found the wrong TMF file. You’re using the 64-bit TMF file on what
is clearly a 32-bit system. Use your head.

However, I suspect the message numbers are the same. Are you absolutely
sure this is from the same dump that has an assertion from KMDF? There
aren’t any user requests at all shown here.


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

Sorry. I got confused. My host computer is AMD64 but the target computer is I386. I loaded the I386 TMF file and the messages are identical.
By the way, there is an assertion but the driver runs on. However, the data from the second part is all 0’s. Here is the debug output before wdflogdump is executed.

*** MyTestDev Reading 4096 bytes @ 0

*** Assertion failed: pBuf != NULL
*** Source File: d:\vistartm\drivers\wdf\kmdf\src\support\fxrequestbuffer.cpp, line 369

Break repeatedly, break Once, Ignore, terminate Process, or terminate Thread (boipt)?o

Execute ‘.cxr F8D1B838’ to dump context
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPoint:
80ab8f5c cc int 3

kd> .cxr F8D1B838
eax=f8d1b838 ebx=00000000 ecx=f8d1bc94 edx=00000000 esi=f8d1bc94 edi=f7c64950
eip=80abac60 esp=f8d1bb10 ebp=f8d1bb24 iopl=0 nv up ei ng nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000292
nt!RtlAssert+0x18:
80abac60 5d pop ebp

xxxxx@yahoo.com wrote:

Sorry. I got confused. My host computer is AMD64 but the target computer is I386. I loaded the I386 TMF file and the messages are identical.
By the way, there is an assertion but the driver runs on. However, the data from the second part is all 0’s. Here is the debug output before wdflogdump is executed.

*** MyTestDev Reading 4096 bytes @ 0

Is that message OK? When it says “@ 0”, does that mean something like
offset 0 within your BAR?

*** Assertion failed: pBuf != NULL
*** Source File: d:\vistartm\drivers\wdf\kmdf\src\support\fxrequestbuffer.cpp, line 369

Break repeatedly, break Once, Ignore, terminate Process, or terminate Thread (boipt)?o

Hopefully, this will be enough to trigger a response from our friends on
the KMDF team.


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

> When it says “@ 0”
This is just output from a KdPrint statement.

xxxxx@yahoo.com wrote:

> When it says “@ 0”
>
This is just output from a KdPrint statement.

I am, of course, fully aware of that. It says “4096 @ 0”, which implies
to me that you are sending 4,096 bytes to an address 0 somewhere. I was
just trying to find out whether you really had a null pointer, or if
that was referring to “offset 0” within a register space of some kind.


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

Oh, these are value of Length (8 sectors) and parameters.Parameters.Read.DeviceOffset (0) in the EvtDeviceRead handler. Basically, I need to build 2 buffers which are subrange of the output buffer. The first buffer (1 sector) will be filled with data from a file, and the second buffer (7 sectors) will be filled from the block device.

If it’s just this scenario, then a simple(non-optimal!) solution would
be first read 8 sectors from disk (offset 0) and then pass this same
buffer to ZwReadFile to read 1 sector from file.

-----Original Message-----
From: xxxxx@yahoo.com [mailto:xxxxx@yahoo.com]
Sent: Thursday, December 18, 2008 9:02 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Split an IO request

Oh, these are value of Length (8 sectors) and
parameters.Parameters.Read.DeviceOffset (0) in the EvtDeviceRead
handler. Basically, I need to build 2 buffers which are subrange of the
output buffer. The first buffer (1 sector) will be filled with data
from a file, and the second buffer (7 sectors) will be filled from the
block device.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

Unfortunately, in most cases, data will come from multiple files and devices.

It seems calling WDF_MEMORY_DESCRIPTOR_INIT_HANDLE with a non-null PWDFMEMORY_OFFSET will result in the assertion. Even if the WDFMEMORY_OFFSET represent the whole outputbuffer (offset = 0, length = length of outputbuffer). By the way, I must have been hallucinating yesterday. Today, when I check the buffer content in the user mode app, its content contains correct data for all 8 sectors.

I checked the KMDF samples sources and it seems they all use IoBuildPartialMdl to split the request buffer. I tried that approach and so far so good, no assertion or blue-screen yet.

My next question is when accessing the request buffer described by an MDL using MmGetSystemAddressForMdlSafe, do I need to call MmProbeAndLockPages? I saw some samples do that and some don’t. Thanks.

In general you only need to call MmProbeAndLockPages if you are building the
MDL from scratch from user mode or paged pool.
Which samples were using IoBuildPartialMdl and then calling
MmProbeAndLockPages on the new partial Mdl? Those would be buggy samples.

Mark Roddy

On Tue, Dec 23, 2008 at 5:19 PM, wrote:

> I checked the KMDF samples sources and it seems they all use
> IoBuildPartialMdl to split the request buffer. I tried that approach and
> so far so good, no assertion or blue-screen yet.
>
> My next question is when accessing the request buffer described by an MDL
> using MmGetSystemAddressForMdlSafe, do I need to call MmProbeAndLockPages?
> I saw some samples do that and some don’t. Thanks.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

You are correct. The mdl is not from a IoBuildPartialMdl.

> My next question is when accessing the request buffer described by an MDL using

MmGetSystemAddressForMdlSafe, do I need to call MmProbeAndLockPages?

No.

For the MDL associated with the IRP (Irp->MdlAddress), MmProbeAndLockPages is already done for you.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com