Sending IOCTR or IRP to a child from parent or userspace

Hi all,

I’m not sure if my terminology is correct and if I understood the driver I need to extend to 100%.

My driver is WDM and most of it is out from the book Walter Oney: “Programming The Microsoft Windows Driver Model”(2003).
I have a controller driver which handles the PnP when the USB device is connected.
In the StartDevice routine of this driver (I will call it parent) a child device is added. This child is a port mini driver for audio IO.
I hope this is correct explained.

The child is created by “IoCreateDevice”
PDEVICE_OBJECT child;
status = IoCreateDevice(
pdx->DriverObject,
sizeof(PDO_EXTENSION),
NULL,
FILE_DEVICE_BUS_EXTENDER,
FILE_AUTOGENERATED_DEVICE_NAME|FILE_DEVICE_SECURE_OPEN,
FALSE,
&child);

Now what I want is send a IRP or IOCTR or whatever message from either the controller driver (parent) or from user space direct to this driver and I’m digging in mud and have no idea how to do this right now. I have a communication path from the child to the parent with some dispatch messages but right now I have no idea how to turn this and send an initial message back from parent to child.

Thaks and best regards,
K. Weller

You are using a 17-year-old text to create your driver. Why would you do that? The Windows world is a substantially different place now. You should probably throw out what you’ve done and write a KMDF driver from scratch. You would be much better served in the long run.

As a rule, driver messages always flow from the top down: from user mode to a top-level driver to its parent drivers until it reaches a bottom-level bus driver. You can’t send an IRP outward. Now, your user-mode application can certainly open a handle to the audio driver. You can create a device interface to allow the app to find the driver. You will need to override the dispatching; for audio drivers, the Port Class driver normally takes over all of the dispatching, and it won’t know how to handle your custom ioctls.

If you really need to call up into your audio driver, there’s a cheating way to do that. The audio driver can send an IRP_MJ_INTERNAL_DEVICE_CONTROL request to the bus driver, and pass a set of function pointers, kind of like a C++ virtual function table. The bus driver can save that set of function pointers and call them at will. You just have to be very careful to get rid of those pointers when you remove the device.

Thanks Tim,

well the driver is old and I maintain it. So changing it to KMDF is not a soulution right now.

Now, your user-mode application can certainly open a handle to the audio driver.
This is what I first tried without success. I was not able to get the handle to the port with the SetupAPI. I also comunicate with my parent driver liek this so I was aware of it. Maybe here is my issue.
Question:
Should the Port Class driver like I described above also be accessible from user-mode, so I can send the DeviceIOControl direct to it ?
Or must I change something during creating the child to make it accessible from user-mode ?

Beside this:
You keyword “IRP_MJ_INTERNAL_DEVICE_CONTROL” showed me up a new way to look for a solution. Thank you for this !

Before I start this, I might ask the qeustion a bit different.

In my parent driver, which gets all the knowlege how the hardware is configured right now, I need to call back to the Port Class audio driver somehow. For example I will get the notification from my hardware that the users puged in a jack to port XY and I want to reflect this int my Port Class driver. How can I exchange this event ?

From my parent up to user-mode, down via DeviceIOControl (if possible like I asked above) ?

Thanks and regards,
K. Weller

Your Port Class driver is definitely reachable from user mode. That is, after all, how the Audio Engine gets in to the driver to do its work. There is a bit of a “secret handshake” involved. Kernel Streaming uses the file name extension ability extensively. It will open one file (“/global”) for doing its property investigation, then another file to open the filter, and another file to open the pins. And when they open the pins, the file name actually includes a 100-or-so-byte binary structure that defines the final negotiated format.

Because of that, I usually create my own device interface, with a custom suffix. I then intercept IRP_MJ_CREATE to look for my suffix, and I don’t allow Port Class to dispatch that.

The question you asked is exactly what I mentioned in my final paragraph. Your audio driver can send an IRP down that includes a set of function pointers. The parent driver can then call back into those functions. It’s kind of like a COM interface.

Thanks again Tim for the details!

I started to go this way and send the IRP down during my child his “AddDevice” down to my parent to pass in some function pointers.

Quick question about this:

Because of that, I usually create my own device interface, with a custom suffix. I then intercept IRP_MJ_CREATE to look for my suffix, and I don’t allow Port Class to dispatch that.

Can you explains this a little more what you doing here ?
I don’t get this fully I guess.

Again: thanks for you help and your time !

Best regards,
K. Weller

The “suffix” that Tim’s talking about a device namespace. When you get the IRP_MJ_CREATE look at the “namespace” will be described by the FileName field of the FILE_OBJECT. What you’ll see there is the part of the “filename” that remains after the Object Manager has parsed (and removed) the part of the name that corresponds with the device.

Peter

I am glad that others have responded first, but let me make a couple of observations

  1. you are making a significant change to a long established driver
  2. given 1, you are unwilling to make commensurate decisions

If I am wrong with respect to #1, than why do we need new channels of communication? And it I am right about #1, the choice of moving to KMDF will certainly allow you to complete your work months or years sooner

The documentation calls it a “reference string”:
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-ioregisterdeviceinterface
When a user-mode app uses that device interface to open the driver, the FileName member of the FILE_OBJECT will contain that reference string. The Kernel Streaming interfaces used for audio and video use these reference strings extensively.

Hi all,

thanks for explaining this to me. I just saw yesterday the:
https://community.osr.com/discussion/292091/sysdriver-how-to-capture-input-data-and-play-user-audio-application-data/p1
parallel thread about the sysvad audio driver which covers some of this topic too I think.

@MBond2

  1. well yes you are right.
  2. well it is always a question about what is more work or is it it worth to change the existing or to start from scratch. Even if it is possible more easy to handle and maintain a KMDF driver I think, in this case, even if your point 1) is correct it still was a matter of not understanding everything fully from my side. So I guess I would have had the same issue some how also with KMDF drivers. So I hope my learning here will help me in the future.

So thank you all agin for your help and your input !

Best regards,
K. Weller

The documentation calls it a “reference string”:

Ah! …my apologies. I did not realize the OP was opening a device interface GUID. Rather I though he was opening an ordinary sym link by name.

Reference string for a Device Interface GUID; Namespace for the “filename” when opening a device by name.

Peter