WdfRequestRetrieveOutputBuffer() question

Doron, Maxim, thanks for your replies. That was very helpful.

Another question is about WdfRequestRetrieveOutputBuffer() – from my understanding, it is used to get the outputBuffer we associated with outputMem WDFMEMORY object in WdfIoTargetFormatRequestForInternalIoctl.

status = WdfIoTargetFormatRequestForInternalIoctl(
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
fdoData->WdfRequest,
IoctlControlCode,
inputMem,
NULL,
outputMem,
NULL
);

After getting the IOCTL in the lower level Driver, it is giving a different Out buffer address than what I passed in from the driver above. Even if I assume that maybe the framework is using its own buffer and will copy things later on to Out Buffer associated with outputMem WDFMEMORY object, I did not see that happen.

I retrieve the Out Buffer in my completion routine like this, it doesn’t reflect the Out data I expect (I do know that different Outbuffer address does have the Out data I need):

VOID
SendIOCTLToTargetAsyncComplete(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
PDEV_INFO pDevInfo;
WDFMEMORY WdfMemoryHandle;
PFDO_EXTENSION fdoData = (PFDO_EXTENSION)Context;

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“–>SendIOCTLToTargetAsyncComplete\n”);

WdfMemoryHandle = CompletionParams->Parameters.Ioctl.Output.Buffer;
pDevInfo = (PDEV_INFO)WdfMemoryGetBuffer(WdfMemoryHandle, NULL);

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“<–SendIOCTLToTargetAsyncComplete\n”);

return;
}

Wondering if I am missing something.

Thanks,
Vidya
PS: WdfRequestRetrieveInputBuffer() works fine, I saw it retrieved the same Input Buffer address originally passed. I actually tried to include the output buffer/data I need in the Input Buffer! But I could not “write” anything into the Input Buffer (it is only for reading any input data I believe).

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Sunday, March 01, 2009 8:33 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WDFREQUEST handle changing in the lower level driver

Completely by design. All handles are specific to the driver, usually specific to the WDFDEVICE. Underneath the covers, KMDF uses WDM when sending io so all the lower driver sees is a PIRP which the lower driver allocates its own WDFREQUEST for.

WDF object handles are not a way to share state/information across different drivers. Put your additional data in the request input buffer itself.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Dharmaraju, Vidyadhari
Sent: Sunday, March 01, 2009 8:20 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] WDFREQUEST handle changing in the lower level driver

I am sending an IOCTL like this to a lower level driver (driver below) along with a WDFREQUEST – the WDFREQUEST handle is showing a different address (in the lower level driver) from what I sent.

status = WdfIoTargetFormatRequestForInternalIoctl(
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
fdoData->WdfRequest,
IoctlControlCode,
inputMem,
NULL,
outputMem,
NULL
);
if (!NT_SUCCESS(status)) {
return status;
}

WdfRequestSetCompletionRoutine(
fdoData->WdfRequest,
SendIOCTLToTargetAsyncComplete,
NULL
);

if (WdfRequestSend(
fdoData->WdfRequest,
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
WDF_NO_SEND_OPTIONS
) == FALSE) {
status = WdfRequestGetStatus(fdoData->WdfRequest);
}

I have also associated the WDFREQUEST with a “requestContext” like this:

WDF_OBJECT_ATTRIBUTES_INIT(&attrib);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
&attrib,
REQUEST_CONTEXT
);
status = WdfObjectAllocateContext(
fdoData->WdfRequest,
&attrib,
&reqContext
);
attribsTwo.ParentObject = fdoData->WdfRequest;

I made sure the “reqContext” is valid and associated with fdoData->WdfRequest by getting the context with reqContext = GetRequestContext(fdoData->WdfRequest);

This is the debugger info about the WDFREQUEST at this point (driver that is sending the IOCTL):

kd> !wdfrequest 0x76967dd0
!IRP 0x89263150

State: Allocated by driver, IRP allocated by WDF
!WDFIOTARGET 0x763cea98

After I receive the IOCTL_I_Sent, in the lower level driver, somehow the WDFREQUEST address is different in the lower driver than when it was created and sent from the driver above. Also, when I try to do –
reqContext = GetRequestContext(fdoData->WdfRequest), this gives me a NULL reqContext.

This is associated debug output:

3: kd> g
Breakpoint 7 hit
MyDrv!SendIOCTLToTargetAsync+0x10d:
bac29ffd 6a00 push 0
3: kd> g
==> PORT_EvtInternalIoDeviceControl
==> PORT_PDOInternalIoControl
InternalIoCntl: 0x222460
Breakpoint 1 hit
Port!PORT_PDOInternalIoControl+0x2d7:
b9b47167 8b550c mov edx,dword ptr [ebp+0Ch]

This shows the WDFREQUEST in the lower level driver:-

3: kd> !wdfrequest 0x76dd0918
!IRP 0x89263150

!WDFQUEUE 0x762ece08
State: Pending, Allocated by WDF for incoming IRP

3: kd> p
Port!PORT_PDOInternalIoControl+0x2e3:
b9b47173 6a00 push 0
3: kd> !wdfqueue 0x762ece08

Dumping WDFQUEUE 0x762ece08

Parallel, Default, Power-managed, PowerOn, Can accept, Can dispatch, ExecutionLevelDispatch, SynchronizationScopeNone
Number of driver owned requests: 2
!WDFREQUEST 0x76d5a408 !IRP 0x00000000
!WDFREQUEST 0x76dd0918 !IRP 0x89263150
Number of waiting requests: 0

Any clue on what may be going wrong and why the WDFREQUEST passed is “DIFFERENT” from what I sent, obviously that is why I am not able to fetch the “reqContext” associated with the WDFREQUEST.

Any ideas?

Thanks!
Vidya


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


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

WdfIoTargetFormatRequestForInternalIoctl behaves like the IO manager IoBuildXxx calls in the sense that it will allocate double buffer if the IOCTL code specifies that it is METHOD_BUFFERED (it does not create a threaded irp though). Upon completion KMDF will copy back into the original output buffer. This is why you are seeing a different raw buffer pointer in the lower driver.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Dharmaraju, Vidyadhari
Sent: Monday, March 02, 2009 11:31 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] WdfRequestRetrieveOutputBuffer() question

Doron, Maxim, thanks for your replies. That was very helpful.

Another question is about WdfRequestRetrieveOutputBuffer() – from my understanding, it is used to get the outputBuffer we associated with outputMem WDFMEMORY object in WdfIoTargetFormatRequestForInternalIoctl.

status = WdfIoTargetFormatRequestForInternalIoctl(
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
fdoData->WdfRequest,
IoctlControlCode,
inputMem,
NULL,
outputMem,
NULL
);

After getting the IOCTL in the lower level Driver, it is giving a different Out buffer address than what I passed in from the driver above. Even if I assume that maybe the framework is using its own buffer and will copy things later on to Out Buffer associated with outputMem WDFMEMORY object, I did not see that happen.

I retrieve the Out Buffer in my completion routine like this, it doesn’t reflect the Out data I expect (I do know that different Outbuffer address does have the Out data I need):

VOID
SendIOCTLToTargetAsyncComplete(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
PDEV_INFO pDevInfo;
WDFMEMORY WdfMemoryHandle;
PFDO_EXTENSION fdoData = (PFDO_EXTENSION)Context;

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“–>SendIOCTLToTargetAsyncComplete\n”);

WdfMemoryHandle = CompletionParams->Parameters.Ioctl.Output.Buffer;
pDevInfo = (PDEV_INFO)WdfMemoryGetBuffer(WdfMemoryHandle, NULL);

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“<–SendIOCTLToTargetAsyncComplete\n”);

return;
}

Wondering if I am missing something.

Thanks,
Vidya
PS: WdfRequestRetrieveInputBuffer() works fine, I saw it retrieved the same Input Buffer address originally passed. I actually tried to include the output buffer/data I need in the Input Buffer! But I could not “write” anything into the Input Buffer (it is only for reading any input data I believe).

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Sunday, March 01, 2009 8:33 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WDFREQUEST handle changing in the lower level driver

Completely by design. All handles are specific to the driver, usually specific to the WDFDEVICE. Underneath the covers, KMDF uses WDM when sending io so all the lower driver sees is a PIRP which the lower driver allocates its own WDFREQUEST for.

WDF object handles are not a way to share state/information across different drivers. Put your additional data in the request input buffer itself.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Dharmaraju, Vidyadhari
Sent: Sunday, March 01, 2009 8:20 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] WDFREQUEST handle changing in the lower level driver

I am sending an IOCTL like this to a lower level driver (driver below) along with a WDFREQUEST – the WDFREQUEST handle is showing a different address (in the lower level driver) from what I sent.

status = WdfIoTargetFormatRequestForInternalIoctl(
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
fdoData->WdfRequest,
IoctlControlCode,
inputMem,
NULL,
outputMem,
NULL
);
if (!NT_SUCCESS(status)) {
return status;
}

WdfRequestSetCompletionRoutine(
fdoData->WdfRequest,
SendIOCTLToTargetAsyncComplete,
NULL
);

if (WdfRequestSend(
fdoData->WdfRequest,
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
WDF_NO_SEND_OPTIONS
) == FALSE) {
status = WdfRequestGetStatus(fdoData->WdfRequest);
}

I have also associated the WDFREQUEST with a “requestContext” like this:

WDF_OBJECT_ATTRIBUTES_INIT(&attrib);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
&attrib,
REQUEST_CONTEXT
);
status = WdfObjectAllocateContext(
fdoData->WdfRequest,
&attrib,
&reqContext
);
attribsTwo.ParentObject = fdoData->WdfRequest;

I made sure the “reqContext” is valid and associated with fdoData->WdfRequest by getting the context with reqContext = GetRequestContext(fdoData->WdfRequest);

This is the debugger info about the WDFREQUEST at this point (driver that is sending the IOCTL):

kd> !wdfrequest 0x76967dd0
!IRP 0x89263150

State: Allocated by driver, IRP allocated by WDF
!WDFIOTARGET 0x763cea98

After I receive the IOCTL_I_Sent, in the lower level driver, somehow the WDFREQUEST address is different in the lower driver than when it was created and sent from the driver above. Also, when I try to do –
reqContext = GetRequestContext(fdoData->WdfRequest), this gives me a NULL reqContext.

This is associated debug output:

3: kd> g
Breakpoint 7 hit
MyDrv!SendIOCTLToTargetAsync+0x10d:
bac29ffd 6a00 push 0
3: kd> g
==> PORT_EvtInternalIoDeviceControl
==> PORT_PDOInternalIoControl
InternalIoCntl: 0x222460
Breakpoint 1 hit
Port!PORT_PDOInternalIoControl+0x2d7:
b9b47167 8b550c mov edx,dword ptr [ebp+0Ch]

This shows the WDFREQUEST in the lower level driver:-

3: kd> !wdfrequest 0x76dd0918
!IRP 0x89263150

!WDFQUEUE 0x762ece08
State: Pending, Allocated by WDF for incoming IRP

3: kd> p
Port!PORT_PDOInternalIoControl+0x2e3:
b9b47173 6a00 push 0
3: kd> !wdfqueue 0x762ece08

Dumping WDFQUEUE 0x762ece08

Parallel, Default, Power-managed, PowerOn, Can accept, Can dispatch, ExecutionLevelDispatch, SynchronizationScopeNone
Number of driver owned requests: 2
!WDFREQUEST 0x76d5a408 !IRP 0x00000000
!WDFREQUEST 0x76dd0918 !IRP 0x89263150
Number of waiting requests: 0

Any clue on what may be going wrong and why the WDFREQUEST passed is “DIFFERENT” from what I sent, obviously that is why I am not able to fetch the “reqContext” associated with the WDFREQUEST.

Any ideas?

Thanks!
Vidya


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


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


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 do not see the output being copied into the Original Buffer in my completion routine.

I retrieve the Out Buffer in my completion routine like this, it doesn’t reflect the Out data I expect (I do know that different Outbuffer address does have the Out data I need):

VOID
SendIOCTLToTargetAsyncComplete(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
PDEV_INFO pDevInfo;
WDFMEMORY WdfMemoryHandle;
PFDO_EXTENSION fdoData = (PFDO_EXTENSION)Context;

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“–>SendIOCTLToTargetAsyncComplete\n”);

WdfMemoryHandle = CompletionParams->Parameters.Ioctl.Output.Buffer;
pDevInfo = (PDEV_INFO)WdfMemoryGetBuffer(WdfMemoryHandle, NULL);

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“<–SendIOCTLToTargetAsyncComplete\n”);

return;
}

Vidya

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Monday, March 02, 2009 1:59 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WdfRequestRetrieveOutputBuffer() question

WdfIoTargetFormatRequestForInternalIoctl behaves like the IO manager IoBuildXxx calls in the sense that it will allocate double buffer if the IOCTL code specifies that it is METHOD_BUFFERED (it does not create a threaded irp though). Upon completion KMDF will copy back into the original output buffer. This is why you are seeing a different raw buffer pointer in the lower driver.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Dharmaraju, Vidyadhari
Sent: Monday, March 02, 2009 11:31 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] WdfRequestRetrieveOutputBuffer() question

Doron, Maxim, thanks for your replies. That was very helpful.

Another question is about WdfRequestRetrieveOutputBuffer() – from my understanding, it is used to get the outputBuffer we associated with outputMem WDFMEMORY object in WdfIoTargetFormatRequestForInternalIoctl.

status = WdfIoTargetFormatRequestForInternalIoctl(
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
fdoData->WdfRequest,
IoctlControlCode,
inputMem,
NULL,
outputMem,
NULL
);

After getting the IOCTL in the lower level Driver, it is giving a different Out buffer address than what I passed in from the driver above. Even if I assume that maybe the framework is using its own buffer and will copy things later on to Out Buffer associated with outputMem WDFMEMORY object, I did not see that happen.

I retrieve the Out Buffer in my completion routine like this, it doesn’t reflect the Out data I expect (I do know that different Outbuffer address does have the Out data I need):

VOID
SendIOCTLToTargetAsyncComplete(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
PDEV_INFO pDevInfo;
WDFMEMORY WdfMemoryHandle;
PFDO_EXTENSION fdoData = (PFDO_EXTENSION)Context;

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“–>SendIOCTLToTargetAsyncComplete\n”);

WdfMemoryHandle = CompletionParams->Parameters.Ioctl.Output.Buffer;
pDevInfo = (PDEV_INFO)WdfMemoryGetBuffer(WdfMemoryHandle, NULL);

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“<–SendIOCTLToTargetAsyncComplete\n”);

return;
}

Wondering if I am missing something.

Thanks,
Vidya
PS: WdfRequestRetrieveInputBuffer() works fine, I saw it retrieved the same Input Buffer address originally passed. I actually tried to include the output buffer/data I need in the Input Buffer! But I could not “write” anything into the Input Buffer (it is only for reading any input data I believe).

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Sunday, March 01, 2009 8:33 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WDFREQUEST handle changing in the lower level driver

Completely by design. All handles are specific to the driver, usually specific to the WDFDEVICE. Underneath the covers, KMDF uses WDM when sending io so all the lower driver sees is a PIRP which the lower driver allocates its own WDFREQUEST for.

WDF object handles are not a way to share state/information across different drivers. Put your additional data in the request input buffer itself.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Dharmaraju, Vidyadhari
Sent: Sunday, March 01, 2009 8:20 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] WDFREQUEST handle changing in the lower level driver

I am sending an IOCTL like this to a lower level driver (driver below) along with a WDFREQUEST – the WDFREQUEST handle is showing a different address (in the lower level driver) from what I sent.

status = WdfIoTargetFormatRequestForInternalIoctl(
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
fdoData->WdfRequest,
IoctlControlCode,
inputMem,
NULL,
outputMem,
NULL
);
if (!NT_SUCCESS(status)) {
return status;
}

WdfRequestSetCompletionRoutine(
fdoData->WdfRequest,
SendIOCTLToTargetAsyncComplete,
NULL
);

if (WdfRequestSend(
fdoData->WdfRequest,
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
WDF_NO_SEND_OPTIONS
) == FALSE) {
status = WdfRequestGetStatus(fdoData->WdfRequest);
}

I have also associated the WDFREQUEST with a “requestContext” like this:

WDF_OBJECT_ATTRIBUTES_INIT(&attrib);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
&attrib,
REQUEST_CONTEXT
);
status = WdfObjectAllocateContext(
fdoData->WdfRequest,
&attrib,
&reqContext
);
attribsTwo.ParentObject = fdoData->WdfRequest;

I made sure the “reqContext” is valid and associated with fdoData->WdfRequest by getting the context with reqContext = GetRequestContext(fdoData->WdfRequest);

This is the debugger info about the WDFREQUEST at this point (driver that is sending the IOCTL):

kd> !wdfrequest 0x76967dd0
!IRP 0x89263150

State: Allocated by driver, IRP allocated by WDF
!WDFIOTARGET 0x763cea98

After I receive the IOCTL_I_Sent, in the lower level driver, somehow the WDFREQUEST address is different in the lower driver than when it was created and sent from the driver above. Also, when I try to do –
reqContext = GetRequestContext(fdoData->WdfRequest), this gives me a NULL reqContext.

This is associated debug output:

3: kd> g
Breakpoint 7 hit
MyDrv!SendIOCTLToTargetAsync+0x10d:
bac29ffd 6a00 push 0
3: kd> g
==> PORT_EvtInternalIoDeviceControl
==> PORT_PDOInternalIoControl
InternalIoCntl: 0x222460
Breakpoint 1 hit
Port!PORT_PDOInternalIoControl+0x2d7:
b9b47167 8b550c mov edx,dword ptr [ebp+0Ch]

This shows the WDFREQUEST in the lower level driver:-

3: kd> !wdfrequest 0x76dd0918
!IRP 0x89263150

!WDFQUEUE 0x762ece08
State: Pending, Allocated by WDF for incoming IRP

3: kd> p
Port!PORT_PDOInternalIoControl+0x2e3:
b9b47173 6a00 push 0
3: kd> !wdfqueue 0x762ece08

Dumping WDFQUEUE 0x762ece08

Parallel, Default, Power-managed, PowerOn, Can accept, Can dispatch, ExecutionLevelDispatch, SynchronizationScopeNone
Number of driver owned requests: 2
!WDFREQUEST 0x76d5a408 !IRP 0x00000000
!WDFREQUEST 0x76dd0918 !IRP 0x89263150
Number of waiting requests: 0

Any clue on what may be going wrong and why the WDFREQUEST passed is “DIFFERENT” from what I sent, obviously that is why I am not able to fetch the “reqContext” associated with the WDFREQUEST.

Any ideas?

Thanks!
Vidya


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


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


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


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

FYI,

When I use METHOD_OUT_DIRECT in IOCTL code, I do get Out Data in my completion routine. But, with METHOD_BUFFERED, I do not get the Out data in my completion routine.

This is weird!
Vidya

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Dharmaraju, Vidyadhari
Sent: Monday, March 02, 2009 2:37 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WdfRequestRetrieveOutputBuffer() question

I do not see the output being copied into the Original Buffer in my completion routine.

I retrieve the Out Buffer in my completion routine like this, it doesn’t reflect the Out data I expect (I do know that different Outbuffer address does have the Out data I need):

VOID
SendIOCTLToTargetAsyncComplete(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
PDEV_INFO pDevInfo;
WDFMEMORY WdfMemoryHandle;
PFDO_EXTENSION fdoData = (PFDO_EXTENSION)Context;

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“–>SendIOCTLToTargetAsyncComplete\n”);

WdfMemoryHandle = CompletionParams->Parameters.Ioctl.Output.Buffer;
pDevInfo = (PDEV_INFO)WdfMemoryGetBuffer(WdfMemoryHandle, NULL);

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“<–SendIOCTLToTargetAsyncComplete\n”);

return;
}

Vidya

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Monday, March 02, 2009 1:59 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WdfRequestRetrieveOutputBuffer() question

WdfIoTargetFormatRequestForInternalIoctl behaves like the IO manager IoBuildXxx calls in the sense that it will allocate double buffer if the IOCTL code specifies that it is METHOD_BUFFERED (it does not create a threaded irp though). Upon completion KMDF will copy back into the original output buffer. This is why you are seeing a different raw buffer pointer in the lower driver.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Dharmaraju, Vidyadhari
Sent: Monday, March 02, 2009 11:31 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] WdfRequestRetrieveOutputBuffer() question

Doron, Maxim, thanks for your replies. That was very helpful.

Another question is about WdfRequestRetrieveOutputBuffer() – from my understanding, it is used to get the outputBuffer we associated with outputMem WDFMEMORY object in WdfIoTargetFormatRequestForInternalIoctl.

status = WdfIoTargetFormatRequestForInternalIoctl(
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
fdoData->WdfRequest,
IoctlControlCode,
inputMem,
NULL,
outputMem,
NULL
);

After getting the IOCTL in the lower level Driver, it is giving a different Out buffer address than what I passed in from the driver above. Even if I assume that maybe the framework is using its own buffer and will copy things later on to Out Buffer associated with outputMem WDFMEMORY object, I did not see that happen.

I retrieve the Out Buffer in my completion routine like this, it doesn’t reflect the Out data I expect (I do know that different Outbuffer address does have the Out data I need):

VOID
SendIOCTLToTargetAsyncComplete(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
PDEV_INFO pDevInfo;
WDFMEMORY WdfMemoryHandle;
PFDO_EXTENSION fdoData = (PFDO_EXTENSION)Context;

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“–>SendIOCTLToTargetAsyncComplete\n”);

WdfMemoryHandle = CompletionParams->Parameters.Ioctl.Output.Buffer;
pDevInfo = (PDEV_INFO)WdfMemoryGetBuffer(WdfMemoryHandle, NULL);

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
“<–SendIOCTLToTargetAsyncComplete\n”);

return;
}

Wondering if I am missing something.

Thanks,
Vidya
PS: WdfRequestRetrieveInputBuffer() works fine, I saw it retrieved the same Input Buffer address originally passed. I actually tried to include the output buffer/data I need in the Input Buffer! But I could not “write” anything into the Input Buffer (it is only for reading any input data I believe).

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Sunday, March 01, 2009 8:33 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WDFREQUEST handle changing in the lower level driver

Completely by design. All handles are specific to the driver, usually specific to the WDFDEVICE. Underneath the covers, KMDF uses WDM when sending io so all the lower driver sees is a PIRP which the lower driver allocates its own WDFREQUEST for.

WDF object handles are not a way to share state/information across different drivers. Put your additional data in the request input buffer itself.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Dharmaraju, Vidyadhari
Sent: Sunday, March 01, 2009 8:20 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] WDFREQUEST handle changing in the lower level driver

I am sending an IOCTL like this to a lower level driver (driver below) along with a WDFREQUEST – the WDFREQUEST handle is showing a different address (in the lower level driver) from what I sent.

status = WdfIoTargetFormatRequestForInternalIoctl(
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
fdoData->WdfRequest,
IoctlControlCode,
inputMem,
NULL,
outputMem,
NULL
);
if (!NT_SUCCESS(status)) {
return status;
}

WdfRequestSetCompletionRoutine(
fdoData->WdfRequest,
SendIOCTLToTargetAsyncComplete,
NULL
);

if (WdfRequestSend(
fdoData->WdfRequest,
WdfUsbTargetDeviceGetIoTarget(fdoData->WdfUsbTargetDevice),
WDF_NO_SEND_OPTIONS
) == FALSE) {
status = WdfRequestGetStatus(fdoData->WdfRequest);
}

I have also associated the WDFREQUEST with a “requestContext” like this:

WDF_OBJECT_ATTRIBUTES_INIT(&attrib);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
&attrib,
REQUEST_CONTEXT
);
status = WdfObjectAllocateContext(
fdoData->WdfRequest,
&attrib,
&reqContext
);
attribsTwo.ParentObject = fdoData->WdfRequest;

I made sure the “reqContext” is valid and associated with fdoData->WdfRequest by getting the context with reqContext = GetRequestContext(fdoData->WdfRequest);

This is the debugger info about the WDFREQUEST at this point (driver that is sending the IOCTL):

kd> !wdfrequest 0x76967dd0
!IRP 0x89263150

State: Allocated by driver, IRP allocated by WDF
!WDFIOTARGET 0x763cea98

After I receive the IOCTL_I_Sent, in the lower level driver, somehow the WDFREQUEST address is different in the lower driver than when it was created and sent from the driver above. Also, when I try to do –
reqContext = GetRequestContext(fdoData->WdfRequest), this gives me a NULL reqContext.

This is associated debug output:

3: kd> g
Breakpoint 7 hit
MyDrv!SendIOCTLToTargetAsync+0x10d:
bac29ffd 6a00 push 0
3: kd> g
==> PORT_EvtInternalIoDeviceControl
==> PORT_PDOInternalIoControl
InternalIoCntl: 0x222460
Breakpoint 1 hit
Port!PORT_PDOInternalIoControl+0x2d7:
b9b47167 8b550c mov edx,dword ptr [ebp+0Ch]

This shows the WDFREQUEST in the lower level driver:-

3: kd> !wdfrequest 0x76dd0918
!IRP 0x89263150

!WDFQUEUE 0x762ece08
State: Pending, Allocated by WDF for incoming IRP

3: kd> p
Port!PORT_PDOInternalIoControl+0x2e3:
b9b47173 6a00 push 0
3: kd> !wdfqueue 0x762ece08

Dumping WDFQUEUE 0x762ece08

Parallel, Default, Power-managed, PowerOn, Can accept, Can dispatch, ExecutionLevelDispatch, SynchronizationScopeNone
Number of driver owned requests: 2
!WDFREQUEST 0x76d5a408 !IRP 0x00000000
!WDFREQUEST 0x76dd0918 !IRP 0x89263150
Number of waiting requests: 0

Any clue on what may be going wrong and why the WDFREQUEST passed is “DIFFERENT” from what I sent, obviously that is why I am not able to fetch the “reqContext” associated with the WDFREQUEST.

Any ideas?

Thanks!
Vidya


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


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


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


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


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

Dharmaraju, Vidyadhari wrote:

When I use METHOD_OUT_DIRECT in IOCTL code, I do get Out Data in my completion routine. But, with METHOD_BUFFERED, I do not get the Out data in my completion routine.

This is weird!

Well, not entirely. Is the lower driver also KMDF, or is it standard WDM?

Remember that the transfer mechanism differs based on the IOCTL code.
For METHOD_BUFFERED, the input and output data both share a single
buffer, in Irp->AssociatedIrp.SystemBuffer. For METHOD_OUT_DIRECT, the
input buffer is expected in Irp->AssociatedIrp.SystemBuffer, but the
output data is in Irp->MdlAddress.

For METHOD_BUFFERED, the I/O subsystem handles copying data into and out
of that single buffer at the transition edge between user and kernel
mode. But for a kernel caller, that interface doesn’t exist. A kernel
caller of a METHOD_BUFFERED ioctl must set up SystemBuffer himself, and
use it for both input and output.

However, there’s something about this that confuses me. Your code was
using WdfUsbTargetDeviceGetIoTarget, which would only be used to send
URBs down into USBD. Is that what you are doing? If so, then none of
this crap matters at all. URBs are sent through an INTERNAL ioctl,
where the standard buffering methods don’t apply. What ioctl are you
trying to send?


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

>A kernel caller of a METHOD_BUFFERED ioctl must set up SystemBuffer himself, and

use it for both input and output.

How do we achieve this? I am not completely clear on this. Set up the System Buffer where the IOCTL is originating? --How exactly do we do this? (because, my understanding is, framework associates an IRP with the WDFREQUEST when we send WdfIoTargetFormatRequestForInternalIoctl()). And retrieve it in the lower level driver when the IOCTL is received? And copy the Out Data into it?

However, there’s something about this that confuses me. Your code was
using WdfUsbTargetDeviceGetIoTarget, which would only be used to send
URBs down into USBD. Is that what you are doing? If so, then none of
this crap matters at all. URBs are sent through an INTERNAL ioctl,
where the standard buffering methods don’t apply. What ioctl are you
trying to send?

The Lower driver is also KMDF.

I am not trying to send an URB in this particular case. I am trying to send my_own custom IOCTL, to request Host Controller to do something for me.

Thanks!
Vidya