WdfIoTargetCreate: How to get the WDFDEVICE used as first parameter?

Hello,

We have a kmdf, software only, non-Pnp driver. In the driver's main source file,
we do the following to set up a context area that holds the WDFDEVICE
for the driver.

**************** CONTEXTAREA.H ***************
typedef struct _REQUEST_CONTEXT
{
WDFDEVICE wdfDevice;
} REQUEST_CONTEXT, *PREQUEST_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, GetRequestContext)
***************************************

*********** DRIVER.C *********************
(error checking removed for brevity)
#include "contextarea.h"
.
.
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT);
status = WdfDeviceCreate(&DeviceInit,
&attributes,
&controlDevice);
// Save the WDFDEVICE in our context area so
// source code in external functions outside of
// this file can access it.
context = GetRequestContext(controlDevice);
context->wdfDevice = controlDevice;
*******************************************

************** DOIOCTL.C **********************
// In this file we have an IOCTL function that is called
// by the main driver code to do a task.
#include "contextarea.h"
.
.
NTSTATUS DoMyIOCTL(
IN WDFREQUEST theRequest,
IN size_t theInputBufferLength,
IN size_t theOutputBufferLength,
IN OUT size_t *bytesCopied)

// We need to send an IOCTL request to another
// device. We need to retrieve the WDFDEVICE
// for our driver from the context area so
/// WdfIoTargetCreate() will know the source of
// the IOCTL request.
//
// So, I assumed that I would call the context
// area accessor, but it failed and required
// the WDFDEVICE as a parameter, which we we
// saved in the context area! A bit of the
// chicken before the egg...

// So, I am hoping that someone can tell me how I can make the following
// code work. Once I have the ioTarget, the rest should flow pretty easily.

Thank you for your comments and help!
Mike

context = GetRequestContext();
status = WdfIoTargetCreate(WdfIoTargetGetDevice(context->wdfDevice),
WDF_NO_OBJECT_ATTRIBUTES, &ioTarget);

I don’t think I understand the question. There’s a lot of random code there, and some comments that might have a question in it.

Are you saying you want DriverB to get the context area associated with a WDFDEVICE in (untimrely unrelated) DriverA?

I don’t believe you can do that,

Peter
OSR

Hi Peter,

Sorry for the confusion in my initial posting… My goal is to send IOCTL_STORAGE_QUERY_PROPERTY, using the Framework, to each disk device in the local system so I can get information about them. Here are my specific questions and generic code for what I am trying to do.

  1. Is there a query that I can make of my driver to get its WDFDEVICE handle, so I can use it with WdfIoTargetCreate()? I couldn’t find such a query, so I created a context area in another source file, that is part of our driver. In its add device function, I created a context area that contained a WDFDEVICE varaible. After we create the device in the add device function, I save the handle to the context area. My thought was that when I get to the other source code file that contains the following code, I could easily retrieve the WDFDEVICE from the context area and go on my way… But, late, late at night, I discovered that in order to access the context area, I have to have the WDFDEVICE handle, so this approach is not going to work.

Another alternative would be to create a global variable in the source file that creates the device, and access it via extern in the file that contains the following code, but, like everyone, I don’t like globals, so I don’t like this idea.

  1. A related question concerns th proper disposal of objects when using IOGetDeviceObjectPointer(). Should I call ObDereferenceObject(pFO) and ObDereferenceObject(pDO) in the loop in the following code to release these objects after I’ve sent my IOCTL request? I assume it should be done, but the documentation for IOGetDeviceObjectPointer() doesn’t make it clear to me.

I would really appreciate your comments on what is the best way to proceed with these two questions… I hope that this new description is more helpful. :slight_smile:

Thank you for your help!

Mike

// Get the list of symbolic names.
status = IoGetDeviceInterfaces(&GUID_DEVINTERFACE_DISK, NULL, 0, &pDeviceList);
if (NT_SUCCESS(status))
{
// Okay, let’s walk the list of devices…
p = pDeviceList;

while (*p != UNICODE_NULL && NT_SUCCESS(status))
{
lengthInBytes = (USHORT) wcslen(p) * (USHORT) sizeof(wchar_t);
status = MyUnicodeString_Create(&name, p, lengthInBytes, lengthInBytes);
if (NT_SUCCESS(status))
{
// Get the device object pointer… I don’t care about the file object pointer.
status = IoGetDeviceObjectPointer((PUNICODE_STRING)name, FILE_ALL_ACCESS, &pFO, &pDO);
if (NT_SUCCESS(status))
{
// Here is where I hit the wall… In order to send an IOCTL request to the device,
// I need to create a remote IO target. In order to create the IO target, I need
// the WDFDEVICE representing our kmdf, non-PnP, software only driver.

// Retrieve our WDFDEVICE from the context area…
context = GetRequestContext(???);
status = WdfIoTargetCreate(WdfIoTargetGetDevice(context->wdfDevice), …
.
.
.
// Release resources… Is this necessary?
ObDereferenceObject(pDO);
ObDereferenceObject(pFO);
}
}
} // while
}

In your io dispatch routine

WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request))

What is MyUnicodeString_Create? Just call RtlInitUnicodeString since already have a null terminated string. The answer to your IoGetDeviceObjectPointer question can be easily found by looking at any of the samples that call the API (you just deref the pfileobject)…BUT, there is no point in calling that API if you are going to create a WDFIOTARGET. You already have the name you want to open, just open the target with a params initialized by WDF_IO_TARGET_OPEN_PARAMS_INIT_CREATE_BY_NAME (see http://msdn.microsoft.com/en-us/library/ff552377(VS.85).aspx, it even mentions device interfaces!)

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@a-bit-of-help.com
Sent: Saturday, March 26, 2011 2:39 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WdfIoTargetCreate: How to get the WDFDEVICE used as first parameter?

Hi Peter,

Sorry for the confusion in my initial posting… My goal is to send IOCTL_STORAGE_QUERY_PROPERTY, using the Framework, to each disk device in the local system so I can get information about them. Here are my specific questions and generic code for what I am trying to do.

  1. Is there a query that I can make of my driver to get its WDFDEVICE handle, so I can use it with WdfIoTargetCreate()? I couldn’t find such a query, so I created a context area in another source file, that is part of our driver. In its add device function, I created a context area that contained a WDFDEVICE varaible. After we create the device in the add device function, I save the handle to the context area. My thought was that when I get to the other source code file that contains the following code, I could easily retrieve the WDFDEVICE from the context area and go on my way… But, late, late at night, I discovered that in order to access the context area, I have to have the WDFDEVICE handle, so this approach is not going to work.

Another alternative would be to create a global variable in the source file that creates the device, and access it via extern in the file that contains the following code, but, like everyone, I don’t like globals, so I don’t like this idea.

  1. A related question concerns th proper disposal of objects when using IOGetDeviceObjectPointer(). Should I call ObDereferenceObject(pFO) and ObDereferenceObject(pDO) in the loop in the following code to release these objects after I’ve sent my IOCTL request? I assume it should be done, but the documentation for IOGetDeviceObjectPointer() doesn’t make it clear to me.

I would really appreciate your comments on what is the best way to proceed with these two questions… I hope that this new description is more helpful. :slight_smile:

Thank you for your help!

Mike

// Get the list of symbolic names.
status = IoGetDeviceInterfaces(&GUID_DEVINTERFACE_DISK, NULL, 0, &pDeviceList); if (NT_SUCCESS(status)) {
// Okay, let’s walk the list of devices…
p = pDeviceList;

while (*p != UNICODE_NULL && NT_SUCCESS(status))
{
lengthInBytes = (USHORT) wcslen(p) * (USHORT) sizeof(wchar_t);
status = MyUnicodeString_Create(&name, p, lengthInBytes, lengthInBytes);
if (NT_SUCCESS(status))
{
// Get the device object pointer… I don’t care about the file object pointer.
status = IoGetDeviceObjectPointer((PUNICODE_STRING)name, FILE_ALL_ACCESS, &pFO, &pDO);
if (NT_SUCCESS(status))
{
// Here is where I hit the wall… In order to send an IOCTL request to the device,
// I need to create a remote IO target. In order to create the IO target, I need
// the WDFDEVICE representing our kmdf, non-PnP, software only driver.

// Retrieve our WDFDEVICE from the context area…
context = GetRequestContext(???);
status = WdfIoTargetCreate(WdfIoTargetGetDevice(context->wdfDevice), …
.
.
.
// Release resources… Is this necessary?
ObDereferenceObject(pDO);
ObDereferenceObject(pFO);
}
}
} // while
}


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

Hi Doron,

I’ve just returned to the office and found your posting! Your code snippet was exactly what I needed to know! Thank you! I am able to send my IOCTL request and everything is working properly!

WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request))