Does KMDF support EXPORT_DRIVERS?

Can I write a kernel mode dll (TARGETTYPE=EXPORT_DRIVER) using the KMDF framework? If so, what restrictions are there compared to normal KMDF drivers?

The initial problem I’m facing is how to get the Driver Object for the dll, if it exists: DriverEntry, which must be supplied, isn’t called (and DllInitialize isn’t passed a driver object).

My dll is loaded by another kmdf driver linked against it but the initialisation routine of my dll, which is called at the end of the client driver’s DriverEntry, blue screens when it calls WdfCollectionCreate; I suspect because there has been no prior call of WdfDriverCreate in the dll, so the default parent doesn’t exist - there has been a successful call of WdfDriverCreate in the client driver.

A search of the archives didn’t turn anything up, although google did cough up an interesting blog from Doron (http://blogs.msdn.com/doronh/archive/2006/11/02/weird-side-affect-of-the-day-defines-can-be-used-in-your-def-file.aspx) which tells me that EXPORT_DRIVERS are used within KMDF, but not whether they themselves use any of the facilities (like collections).

Don

Right now, you can’t write an export driver which uses KMDF. The problem is two fold:

  1. the PDRIVER_OBJECT issue, e.g. the export driver doesn’t have one and using the client driver’s PDRIVER_OBJECT doesn’t work if the export driver is referenced by 2 clients

  2. there is no KMDF client driver stub for an export driver. For a normal KMDF driver, you link against wdfdriverentry.lib and the entrypoing into the driver is modified to point to a function in wdfdriverentry.lib. this new entry point communicates with the KMDF loader (wdfldr.sys) to bind the framework (e.g. the jump table WdfFunctions) before calling your DriverEntry(). This means that your export driver cannot call any KMDF functions, including WdfDriverCreate, because the jump table is not resolved when DllInitialize is called. Creating an export driver stub ala wddriverentry.lib is more difficult to pull off transparently because unlike an entrypoint which can be changed on the command line, DllInitialize is called explicitly by name by the memory manager when the export driver has loaded.

The blog entry you refer to is about wdfldr.sys, which is an export driver, but does not use KMDF.

d

I wouldn’t mind calling the routine in wdfdriverentry.lib explicitly in my DllInitialize routine if that were all it would take to make things work (especially if the DriverEntry routine of my export driver was subsequently called with valid parameters). Although, from what you say, it seems that the non existence of a PDRIVER_OBJECT would be a showstopper.

But, even if I manage to bind the framework to my export driver, I suspect my difficulties are only just beginning. What would happen if I were to use WdfRequestComplete to complete a WDFREQEST passed in to my export driver? Would that work, or is there some magic to do with resource reclamation that would be very unhappy?

I’m guessing that I could complete WDFREQUESTs passed in by a KMDF client driver by using a callback routine into that driver which completed them for me. Would that work?

I won’t read too much into “Right now, you can’t …” which implies that there is no fundamental principle which prohibits a KMDF export driver. Even if the framework were enhanced to support KMDF export drivers it’s clear that it wouldn’t happen very soon.

BTW. Apologies if this post appears twice with subtle differences in wording. I typed it in to the message box and, when I hit the “Post Quick Reply” button, it appeared to send it – but I then got sent back to the home page which invited me to log in (again). The original response hasn’t appeared after half an hour, so I think that something just quietly threw it away. I did take some time thinking about your reply before hitting send, so maybe the web page just timed me out. Moral of the story: take note of the “Quick” in “Post Quick Reply”. If you need time to compose your message, do it somewhere else and paste it in just before replying.

Don

overall, something like this would work, but we (the KMDF team) do not currently support this scenario. there are some details which make this difficult today, the lack of a unique PDRIVER_OBJECT is one of them (and something that you could not brute force your way through). Right now you should consider a library instead of an export driver (yes, I know it is not as servicable) if you need to have shared functionality.

d

Of course another approach is to create a common services driver with a
device interface to allow the drives that need the service to call it. A
little more cumbersome than the DLL in someways, but can actually be easier
for multiple version support. This will work with KMDF, since it is a
standard driver.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntdev…
> overall, something like this would work, but we (the KMDF team) do not
> currently support this scenario. there are some details which make this
> difficult today, the lack of a unique PDRIVER_OBJECT is one of them (and
> something that you could not brute force your way through). Right now
> you should consider a library instead of an export driver (yes, I know it
> is not as servicable) if you need to have shared functionality.
>
> d
>

A KMDF handle is supposed to be local to a particular instance of a KMDF driver. Passing handles between 2 difference drivers is not supported either ;). Once we support export drivers, this restriction will work within that framework where a handle in one driver will work with a driver which exports functions.

d

>overall, something like this would work, but we (the KMDF team) do not currently

support this scenario.

I’m not sure which of my suggestions “something like this” refers to. I’m guessing the client driver callback.

there are some details which make this difficult today, the lack of a unique
PDRIVER_OBJECT is one of them (and something that you could not brute force
your way through).

“could not” might be taken as a challenge by some (but not me :slight_smile:

After reading your first response, thinking about it and looking in the DDK to see how calls to framework routines are implemented, I was considering doing without any KMDF objects belonging to the dll itself (so my collection would have to go, but it’s easy enough to replace with an old fashioned linked list). I was also considering remembering each client (KMDF) driver’s WdfDriverGlobals and WdfFunctions values. Then, when I wanted to process a request from a particular client, overwriting the dll’s own WdfDriverGlobals and WdfFunctions with the client driver’s values. I figured that if the dll wasn’t using any KMDF objects of its own I wouldn’t ever need to use the dll’s own WdfDriverGlobals and WdfFunctions; especially as they haven’t been initialised properly.

That way, providing I can manage concurrent requests sensibly, I wouldn’t need a PDRIVER_OBJECT; at least that was the theory.

Right now you should consider a library instead of an export driver (yes, I
know it is not as servicable) if you need to have shared functionality.

Thanks. I’ll take a good look to see whether a library will do (most of) what I want before proceeding any further with an export driver. I don’t really want to head into uncharted territory: I’d much rather stay within what is supported - hence my original question which started this thread.

Once we support export drivers, this restriction will work
within that framework where a handle in one driver will work
with a driver which exports functions.

Do have an idea of when you intend to support export drivers?

Don

Export driver support will not be in the next release (LHS, Vista SP1), we are considering it for the release after that one. (You could manually try to replace WdfFunctions/DriverGlobals on each call, but what about concurrent calls into the export driver by 2 different client drivers? You cannot safely do this if the export driver is trying to service a call from 2 different sources).

d

>what about concurrent calls into the export driver by 2 different client drivers?

Yep. reason I said “providing I can manage concurrent requests sensibly”.

However, following your advice, I’ll investigate the library option first, before going down this route

Don

Just curious: why do you want to use KMDF for an export driver? What do
you think it’s going to give you? Export drivers don’t do PnP/Power,
which seem to me to be 90% of the problem that KMDF was intended to
solve, at least at this stage.

xxxxx@careful.co.uk wrote:

Can I write a kernel mode dll (TARGETTYPE=EXPORT_DRIVER) using the KMDF framework? If so, what restrictions are there compared to normal KMDF drivers?

The initial problem I’m facing is how to get the Driver Object for the dll, if it exists: DriverEntry, which must be supplied, isn’t called (and DllInitialize isn’t passed a driver object).

My dll is loaded by another kmdf driver linked against it but the initialisation routine of my dll, which is called at the end of the client driver’s DriverEntry, blue screens when it calls WdfCollectionCreate; I suspect because there has been no prior call of WdfDriverCreate in the dll, so the default parent doesn’t exist - there has been a successful call of WdfDriverCreate in the client driver.

A search of the archives didn’t turn anything up, although google did cough up an interesting blog from Doron (http://blogs.msdn.com/doronh/archive/2006/11/02/weird-side-affect-of-the-day-defines-can-be-used-in-your-def-file.aspx) which tells me that EXPORT_DRIVERS are used within KMDF, but not whether they themselves use any of the facilities (like collections).

Don


Ray
(If you want to reply to me off list, please remove “spamblock.” from my
email address)

>

Just curious: why do you want to use KMDF for an export
driver?

It would be a replacement of an existing KMDF filter driver

What do you think it’s going to give you?

Extra performance.

Not sure how you can derive that you get more performance by moving code into a different binary.

d

>

Not sure how you can derive that you get more performance by
moving code into a different binary.

It would save the time taken for each Irp to pass through the filter driver. I measured the difference between the filter immediately completing an Ioctl and passing it down to the next driver (which immediately completed it). On the particular hardware I was using it was about 16 microseconds. Replacing the filter with a set of function calls that did the same thing should be much quicker.

That is odd. Essentially the ‘pass the irp down to the next driver’ operation is an indirect function call.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-281840-
xxxxx@lists.osr.com] On Behalf Of Don Ward
Sent: Tuesday, March 27, 2007 7:27 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Does KMDF support EXPORT_DRIVERS?

>
> Not sure how you can derive that you get more performance by
> moving code into a different binary.

It would save the time taken for each Irp to pass through the filter
driver. I measured the difference between the filter immediately
completing an Ioctl and passing it down to the next driver (which
immediately completed it). On the particular hardware I was using it
was about 16 microseconds. Replacing the filter with a set of function
calls that did the same thing should be much quicker.


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

> That is odd. Essentially the ‘pass the irp down to the next driver’

operation is an indirect function call.

Maybe I wasn’t measuring what I thought I was measuring. It’s entirely possible that the bulk of the overhead is due to some stupidity in my filter driver and will still be there if I refactor it into a library or a kernel mode DLL. Perhaps I should do a bit more investigation to find out where the bulk of the time is being spent.

Having said that, the trip through the filter isn’t just a single indirect function call: there is the IO manager processing, the initial KMDF work to put the request in a queue and to extract it again, Creating and initialising the WDFREQUEST context, retrieving the input and output buffers, (followed by my filter code) then extra cycles to format and route the request to the default I/O target etc. It must all add up.

Don

Yes, it all adds up, but by moving it to an export driver, it is adding up in another binary other then your own, so it is still there.

d

> Yes, it all adds up, but by moving it to an export driver, it is

adding up in another binary other then your own, so it is still there.

I’m not sure I understand why it is “still there”: If we start at the layer above my filter, which is over my function driver, the processing is (roughly)

  1. I/O Mgr
  2. KMDF request reception (Filter)
  3. My Filter
  4. KMDF request transmission
  5. I/O Mgr
  6. KMDF request reception (FD)
  7. FD code
  8. Request Completion

If I implement the filter code as a library or a kernel mode DLL we get

  1. I/O Mgr
  2. KMDF request reception (FD)
  3. My filter code, now called via a procedure call
  4. FD code
  5. Request Completion

In effect I should save one lot of I/O manager code, one lot of KMDF request reception, context creation, queuing and buffer unpacking etc. and the code needed to pass the request down the stack plus reclamation of the inflight resources.

Don

> > Yes, it all adds up, but by moving it to an export driver, it is

> adding up in another binary other then your own, so it is still there.

I’m not sure I understand why it is “still there”

Are these 16us really the worst performance bottleneck in the driver?
Optimizing something but a largest performance bottleneck is often useless in
terms of value/man*hours.


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

> Are these 16us really the worst performance bottleneck in the driver?

Optimizing something but a largest performance bottleneck is often useless in
terms of value/man*hours.

I don’t know if it’s the worst performance bottleneck (and I’m aware of how difficult it can be to guess where the bottleneck is without proper instrumentation). But, since its a filter driver, the extra overhead is paid for every request so it would seem a promising place to try speeding things up.

During it’s initialisation phase, the application software sends in excess of 600,000 Ioctls to the driver. The users definitely noticed the difference in start up time between the previous (non KMDF) incarnation of the drivers and the current implementation. The other thing they compare it to is the start time using Linux, which is an order of magnitude less. I’m trying to claw back some of the difference.

Don

Don, have you considered using IRP_MJ_PNP/IRP_MN_QUERY_INTERFACE? It’s sort of a middle ground between using PE/COFF-based dynamic linking and WDM filtering. If it fits your design pattern, you can query for a direct-call interface, and then the only penalty to jump from one driver to the next is a single indirect call – same cost as PE/COFF. And if you do it right, you get better control over binary layout (ABI) of the interface – something that has always been a problem for PE/COFF dynamic linking.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@careful.co.uk
Sent: Thursday, March 29, 2007 10:32 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Does KMDF support EXPORT_DRIVERS?

Are these 16us really the worst performance bottleneck in the driver?
Optimizing something but a largest performance bottleneck is often useless in
terms of value/man*hours.

I don’t know if it’s the worst performance bottleneck (and I’m aware of how difficult it can be to guess where the bottleneck is without proper instrumentation). But, since its a filter driver, the extra overhead is paid for every request so it would seem a promising place to try speeding things up.

During it’s initialisation phase, the application software sends in excess of 600,000 Ioctls to the driver. The users definitely noticed the difference in start up time between the previous (non KMDF) incarnation of the drivers and the current implementation. The other thing they compare it to is the start time using Linux, which is an order of magnitude less. I’m trying to claw back some of the difference.

Don


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