I have been getting quite a few personal emails with specific questions on how to write a driver or how to a specific technology works or how to fix a particular problem.  I welcome the emails, but I want these discussions to be public so that they are searchable by others (and I can’t be having personal email discussions all the time, I need to do my job 😉 ! ).  \Device\Suggestsions doesn’t seem to fit that need, so I am creating this topic to allow folks to post their questions and I will answer them here.

Comments (388)

  1. serg_pery says:

    Hello Doron,

    I’m trying to understand the NDIS, and especially it power management facility.

    We are a starup company, which develops device and driver for wireless netwroks. We need to integrate our WDM miniport NDIS driver in the Windows XP driver stack. The target is NDIS 5.1 (and higher for Vista). We encounterd a problem to add Power Management facilities to our our driver. That is extermely important for mobile systems.

    The problem is that NDIS is only Power Policy Owner in the driver stack. But it is not aware the device specific idle states. Our WDM minport device driver is familiar with the device specific facilities and states, but it is not ALLOWED to manage the device power states. Our device has USB interface, and we are going to use USB Selective Suspend power save mode while the device is idle.

    Could you advise how the NDIS driver as Power Policy Owner can detect a device

    idle state? Is there any special/ function/method in NDIS? Is there any other

    facility that can help to resolve the problem?

    Thanks in addvance and hope for productive cooperation,


    System Engineer

  2. doronh says:

    Avi, this is not possible currently with the way NDIS works.  It will not idle out the device while the machine is running.  It is more complicated then just sending a Dx irp, you would also need NDIS to send a wait wake irp to the device so that it can wake up from the selective suspend state.  Furthermore, as you noted, you cannot send a power irp to the stack because you are not the power policy owner.

    One way around this problem is to have 2 separate device stacks.  One enumerated by the USB host controller.  The 2nd a virtual NDIS miniport.  the virtual NDIS miniport then opens up the USB enumerate device (by using device interface notifications) and then redirects i/o from NDIS to the other stack.  You will have to deal with the situations where either

    1. the USB device is not enumerated because it is not plugged in (the ndis virtual miniport will always be enumerated)
    2. the usb device is plugged in, but currently powered off and cannot respond to the NDIS request.

    By splitting this up into 2 stacks, you are now the power policy owner for the usb enumerated device and you can selectively suspend whenever you want.

    you can implement this solution with KMDF rather easily.  There is the pcidrv sample which shows how to create an NDIS-WDM driver and use WDFIOTARGET to send I/O (in its case down the stack vs another stack, but that is easy to change).  The toastmon sample shows how to register for a device interface notification and open it up.  KMDF also has implemented selective suspend for you, it is not something you should implement on your own in WDM (it is very very complicated).

  3. serg_pery says:

    Could the Windows ACPI driver be used for such purposes?

    There are a few advantages for such approach:

    1. ACPI driver stack works "transparently" to rest of OS environment.

    2. ACPI driver is nativelly handles power management issues.

    3. The target is very specific operations, which are lack at NDIS level, can be handled by a vendor provided ACPI stack device driver.

    Please comment that.  

  4. doronh says:

    this won’t work.  acpi can’t change the power state of the deivce on the usb bus itself.  the acpi driver could make the device fall off the usb bus but remain powered on through a separate power line, but each time you suspend the device will disappear (and the user will hear the standard device removal sound).  

    acpi is great at power management issues for devices plugged directly into the mobo, not periperhals (usb devices) connected to thpse devices.

    i have seen attempts at doing this in the past (specifically with side band management of a bluetooth radio on a laptop) and they have all failed b/c the power management of the device needs to be done in the stack itself, not as a sideband mechanism.

  5. VelcroILean says:

    when I call


    just before calling

    WdfRequestSend( Request, WdfDeviceGetIoTarget(Device), NULL);

    I get the following ASSERT :

    *** Assertion failed: !oldCancelRoutine

    ***   Source File: d:ntdriverswdminputhidclassread.c, line 92

    If i call


    AFTER calling

    WdfRequestSend( Request, WdfDeviceGetIoTarget(Device), NULL);

    I get

    *** Assertion failed: !cancelRoutine

    ***   Source File: d:ntdriverswdfkmdfsrccorefxirpqueue.cpp, line 598

    Is WdfRequestMarkCancelable an obsolete API?  If so, how can I be sure that my evtIoRead callback does not continue getting called when I unplug my USB device?


  6. doronh says:

    John, you can only mark a request as cancelable if you own the request and have pended it in a queue.  You are misusing or misunderstanding the purpose of the DDI.

    As soon as you send the request to a WDFIOTARGET (or call IoCallDriver in WDM), you are no longer the owner of the request and cannot pend it.  The driver you are sending the request to (HIDClass in this case) now has ownership of the request and is the entity who can mark it cancelable.

    If you want to cancel a request that you sent, call WdfRequestCancelSentRequest.  Hope that helps 


  7. VelcroILean says:


    When you say "own the request and have pended it in a queue" do you mean something more than registering an evtIoRead via WdfIoQueueCreate?


  8. doronh says:

    Sorry for not being clear, it is not the creation of the queue that matters, it is the current stack location in the request.  Every driver in the stack has a stack location in the irp.  When the request is presented to your driver, the current stack location belongs to your device.  When you send the request to a WDFIOTARGET, the current stack location in the request changes to the WDFIOTARGET’s device and you don’t have the current stack location anymore.   You are only allowed to set a cancel routine if the current stack location is set to your device.  


  9. VelcroILean says:

    By " send the request to a WDFIOTARGET" do you mean, for example, calling

    WdfRequestSend( Request, WdfDeviceGetIoTarget(Device), NULL);



  10. VelcroILean says:

    Then why does the sequence:


    WdfRequestSend( Request, WdfDeviceGetIoTarget(Device), NULL);

    yield the assertion:

    *** Assertion failed: !oldCancelRoutine

    ***   Source File: d:ntdriverswdminputhidclassread.c, line 92


    At the entry to my evtIoRead function, does the current stack location NOT belong to my device?

  11. doronh says:

    there can be only one cancel routine on the request.  As the current stack location on the request, you have the ability to set a cancel routine.  as soon as you send the request, you relinquish the right to the cancel routine.  you are not allowed to send a request with a cancel routine set, nor are you allowed to set a cancel routine on a request that has already been sent.  

    When EvtIoRead is called, the current stack locations belongs to your device, but as i said, when you send a request, you relinquish the ability to own the cancel routine on the request.  If you want to be notified when a request that has been sent has been canceled (and is being completed), set a completion routine before you send the request to the WDFIOTARGET.


  12. VelcroILean says:

    Thanks for the info.

    In another driver:

    When I unplug my device, my completion routine gets called  a few times with Params->IoStatus.Status== STATUS_CANCELLED, which I pass on to WdfRequestComplete(Request,Params->IoStatus.Status);

    After this it gets called (seemingly infinitely) with Params->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED which seems reasonable, except that it continues to eat up CPU time and the driver doesn’t  unload.

    Is there anything that I should be doing in my completion routine to ensure that when my device gets unplugged that all of the activity for the newly unplugged device gets concluded?  If not in the completion routine, then where?


  13. doronh says:

    are you resubmitting the i/o from the completion routine?  if so, you need to back off when you get an error and maintain state about the device.  you could implement EvtDeviceSelfManagedIoInit/Suspend/Restart and implement a flag which the completion routine will look at when it decides to resend I/O or not.  

    what type of device are sending I/O to?  a usb device?

  14. VelcroILean says:

    It turns out that we were implementing EvtDeviceSelfManagedIoInit without implementing any of the other callbacks.

    Implementing EvtDeviceSurpriseRemoval and draining the queue seems to cure the problem.

    BTW, is there anything else that we should be doing, for example, draining the queue when the system shuts down with the device still plugged in?

  15. doronh says:

    You should really evaluate your usage of EvtDeviceSurpriseRemoval (), it is there for completeness rather then integration into the callback model.  Why can’t you move the functionality you have in EvtDeviceSurpriseRemoval () to EvtDeviceSelfManageIoSuspend()?  This way you behave properly on all types of device power down (system power down, graceful remove, surprise remove, idle, etc)

    I don’t know the design of your driver or the device class you are in to answer your 2nd question.

  16. ChrisKelly says:

    Hi Doron,

    I have been doing some digging around on in-stack queued spinlocks and thought you might have an opinion on their use. I frequently find myself in the situation of acquiring a spinlock at DISPATCH_LEVEL which on the face of it seems to be a pretty efficient operation – just three instructions to acquire it and two to release it if the spinlock is not being contended for. In-stack queued spinlocks require 13 instructions to acquire and release in these situations. So if you think contention is a theoritical possibility but very rare it would seem to make sense to use normal spinlocks and use queued spinlocks when contention is expected. Of course there is a large grey area that is more difficult to decide. What is very difficult to assess is the impact on the cache of normal spinlocks when being contended. Do you have a general recommendation when to use queued spinlocks.

    Best wishes

    Chris Kelly

  17. doronh says:

    I would not measure this is in such a micro fashion.  the difference between the 3 and 13 instructions is pretty much nil, what is going to cost you is the IRQL change.  

    First, since you are already at DISPATCH_LEVEL, you should use the AtDpcLevel acquisition routines.  This  will remove the attempted IRQL raise.   Note that you must absolutely know apriori that you are at dispatch level, checking the current IRQL is as big of a hit as calling the non "AtDpcLevel" version.  In pure WDM, this means that you can only call the AtDpcLevel versions in a DPC or while holding another spinlock.  Completion routines do not have a guaranteed IRQL of DISPATCH_LEVEL so you can’t assume the KIRQL there.

    Second, if you want to run on Win2k, you have to use the old style spinlocks, queued spinlocks are only supported on XP and later.

    Third, I would use the queued spinlocks whereever I could instead of the normal spinlock.  In the non contention case, the perf is the same and in the case of contention, the queued locks behave much better with respect to cache coherency.  Spinning on a queued spinlock will not invalidate each of the other CPUs cache lines, while the older style spinlock will cause each of the other CPUs cache to be invalidated b/c of the memory access.  

    Finally, i would use the queued spinlocks even if the lock was not highly contended for.  Why?  Because it might be highly contended in the future and then you would have to change all the callsites (which is problematic b/c the C type for the spinlock is the same so it is hard to catch the callers who acquire it w/the wrong acquisition function)

  18. ChrisKelly says:

    Many thanks Doron – that was very helpful.

    Needless to say I do use the "AtDpcLevel" routines and am very careful to ensure that I am dispatch level. With some driver technologies (e.g. NDIS) you know you are at dispatch level much of the time and for example in NDIS6 there is additional support to tell you what IRQL you are at with APIs that are not always at dispatch level.

    I have always been a bit puzzled at why there is such a hit on changing the IRQL – on the face of it (examining in Windbg) this just consists of a read and write of the APIC TPR (at least on the HAL I am using) followed by a table lookup through HalpVectorToIRQL. Is there something here that is more expensive that I imagine or is the problem with other HALs?

  19. doronh says:

    No, that’s it.  Reading and then writing to the APIC is not cheap.  There were HALs previously that implemented a "lazy" IRQL, essentially it maintained the IRQL in software and only touched the APIC when it to change it.  There was talk of adding this back into the ACPI HAL, but I don’t know what was implemented.

  20. PaulR says:

    I have a USB composite keyboard/trackpad device.  It works fine in its basic HID-boot mode, but we want to take advantage of some firmware features of the trackpad to enhance user experience.  Accessing this requires sending a USB command to a different interface (not the one that the trackpad uses).  It also means reading a proprietary HID report instead of the standard mouse-type report.  To do all this, I’ve written a replacement for the usbccgp driver.  (That may not be the right thing, but I can’t think of a way to access the other interface AND read the non-standard reports)  I want the driver to initialize the trackpad to read the proprietary reports, translate them to standard mouse reports and pass them on (as well as passing on the other device reports as-is).  I have everything working fine in terms of device enumeration and initialization, except that the upper HID stack URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER request never gets to my code.  All other IOCTL_INTERNAL_USB_SUBMIT_URB requests come through just fine.  It appears that the HIDCLASS driver is either not sending them (because it thinks there’s a problem) or that the foundation is intercepting them.  Maybe a PASSIVE_LEVEL problem?  Something else?  Suggestions?



  21. doronh says:

    if you are getting the other IOCTLs, then KMDF is not getting in the way of the xfer URB (KMDF just knows that the request is an internal IOCTL, not what’s inside of it).    it should not be an IRQL issue (you should not be creating passive level queues here though b/c HIDclass will send i/o at dispatch level).  

    I would guess that HIDclass doesn’t like something about the hid descriptor or something else during initialization.  Is the device !’ed out in device manager after you enumerate it?  I have a design question though.  I think you should try to steer as far away from writing a usbggcp replacement as you can.  You have 2 parts here.

    The first is modifying the reports being written to/read from the device.  You could accomplish this with a device lower filter driver that sits between hidusb/HIDClass and the USB enumerated PDO.  You can then modifying any i/o to your heart’s content.  

    The 2nd is what is causing you to write the bus driver, the fact that you need to communicate with a 2nd usb interface.  What device class is the 2nd interface reporting itself as?  is it also HID?  if so, is it another pointing or keyboard device?  If it is HID and not a mouse or keyboard, could you just open a file against the 2nd interface and send a HID report to it?  or is the interface i/o that you want to send not a HID report at all?  

    if that doesn’t work, you could write a device lower filter in between the usbgccp FDO and it’s PDO and send the I/O from that device.  You could implement both filters devices in the same driver.  to distinguish between the 2 filter roles, you can have your installation INF write a devnode registry value which indicates the role.  Or, you could call IoGetDeviceProperty(DevicePropertyHardwareID) and parse the HW IDs returned.  If they do not end with &MI_Xx then you are filtering the usbgccp FDO.  If they do end with &MI_Xx, then you are filtering the usbhid/HIDClass FDO.

  22. PaulR says:

    All enumerated devices showed up fine (no "!").

    The interface I need to access is the keyboard interface.

    I didn’t really want to replace usbccgp.  Thanks for the suggestion — I’m working on filters for usbgccp and usbhid/usbhidclass.


  23. doronh says:

    you could put a device lower filter on the keyboard stack, but then you have sibling enumeration issues (what if the keyboard enumerates after your mouse, what if the keyboard is disabled and you can’t get at it).  putting the filter below the usbgccp FDO solves both problems b/c it is always present & started when the mouse filter device starts.  you still have the issue if the mouse starts before the keyboard part starts and selects its config/interface.  I guess you could solve that by calling select interface on your own in the usbgccp filter device, but that might muck with the assumed state in the above stacks, don’t know.

  24. saravak says:

    Can you point me to any resource to learn how to debug memory dumps. Something more advanced than just !analyze -v. Maybe to find processes in critical sections and other things!

    Thank you


  25. doronh says:

    saravak, there are 3 things i can recommend.  unfortunately there are no books on this

    1)  join the OSR Windbg and NTDEV aliases. the debugger team answers questions on the windbg alias and the NTDEV alias has many people who can answer debugging questions.  see

    2)  goto WHDC (  the debugger page, also has good info to read

    3)  look up the help for !process (.hh !process in a kd or windbg window will bring up the help, otherwise c:debuggersdebugger.chm), it can list every process and every thread in it, including irps on each thread and dispatcher objects being waited on


  26. Prabhakant says:

    I am trying to learn driver programming using the PCIDRV sample from
    KMDF 1.1. I built the PCIDRV sample driver and the NdisEdge driver both
    from KMDF 1.1. Then I installed them, using the netdrv.inf file from
    PCIDRV example, on to my system where I actually have the Intel 82558
    based ethernet adapter. The install seems to go fine, although in the
    WinDebug I see NdisReadConfiguration failure, as shown below. The device
    manager reports the ethernet device as ‘working properly’ in the
    properties. When I hook up this system with another system and do a
    basic network setup with crossover ethernet cable, the Network
    Connection dialog shows the ‘cable unplugged’ for my ethernet card.
    However, if I use the driver that came with Windows XP on this machine
    for this same ethernet card, I am able to do networking just fine. I am
    not sure if I am missing some step in installation  or what. Please
    help. Thank you.

    PCIDRV Sample – Driver Framework Edition
    […] – log truncated by doron
    NDISWDM.SYS:WdfIoTargetOpen failed 0xc0000034
    NDISWDM.SYS:Target device doesn’t exist at this time c0000034
    […]– log truncated by doron

  27. doronh says:

    I asked Eliyas Yajkub and he had this to say:

    All he needs to do is comment the following the line, rebuild the ndis-edge, copy over the new driver, disable and reenable the device and it will work.  By defaul the ndisedge is built to talk to the ndisprot driver.


  28. Jan B. says:


    maybe you can help me on this topic.

    im trying to implement two mousefilters to control the cursor with two mice.

    one for x axis, the other for y axis.

    i took the example from ddk and fared quite well.

    unfortunately lately i’m getting the this error, when installing the filter driver:

    "The name is already in use as either a service name or a service display name."

    i’ve changed everything in the moufiltr.inf and moufiltr.rc to create a different service name, but somehow this doesnt work.

    can you point me into the right direction?

    btw. i’m doing this for my diploma, to replace an expensive electromagnetic tracker with cheap hardware.

    thanks a lot,


    ps: whats the proper way to get rid of a filter driver? for test purposes i think i installed mine 50+ times

  29. doronh says:

    you get the error message because 2 services cannot have the same name….but why are you creating 2 differenct services?   the name in the rc file doesn’t matter, it is the name specified in the INF in the .Services section, specifically the DisplayName value in the service install section.  Did you reboot before trying the rename?  if you modified the services key of the registry by hand, you will need to reboot for the service control manager (SCM) to pick up your changes.

    why can’t the same driver run on both mice, where the driver has a mode to do X or Y manipulation.  also, have you looked into WM_INPUT in windows XP and later?  it allows you to see each mouse independently.

    to get rid of the driver, just install the inbox INF on the device and the driver should unload if the stack can be stopped (for ps2 devices, you will need to reboot for the unload).


  30. Sygnosys says:

    Hi Doran,

    In onw of your posts recently you mentioned traceview. And I was hopping you could help me with an issue that I have with it.

    I’m using the TraceView application version 2.0.15 to do a trace session. After a while  running I has created a somewhat respectable file in size. The strange thing is that if I open it with an Hex Editor it’s mostly filled with (0xFFFF). So for example, for a 19Mb file if I choose to compress using NTFS compression mechanist it will occupies on disk only 2/4Mb.

    I’m doing the ETW output using WPP Preprocessor. Although the same issue occurs for other traces, for example a Kernel Trace.

    So my question is, why is does it generate this big file, can it be "fixed" by some sort of configuration?  For now I’m not using all of the defaults Traceview presents.

  31. doronh says:

    I asked the ETW devs and they had this to say:

    Do not use FlushTimer when starting a trace session. FlushTimer causes partially filled buffers to be written out to disk and because ETL files are written in BufferSize increments this can cause a lot of waisted space. Unused part of the buffer is filled with 0xFF to allow for better compression.

  32. edmaster says:

    Hi All,

    Help me, please.

    I dont know how I can build my File System Driver from VS2003 environment. I created "Makefile Project". Early (in DDK 3790.1830) I used these lines (global paths for understanding):

       cd $(ConfigurationName)

       C:WINDDK5600binx86nmake -nologo -D ..Makefile DEBUG=1

    But now (in WDK 5600) we should use build.exe utility and setenv.bat file (for setting environment). I tried to use these lines (global paths for understanding):

        rem C:WinDDK5600binsetenv.cmd C:WinDDK5600 fre WXP

        cd C:ProjectsMiniSpyMiniSpy


    but it’s not correct. Help me, please!!!


  33. doronh says:

    Edward, building a driver from VS is not supported.  I would not try to do this since the build environment in the DDK is very rich and hard to duplicate line for line, flag for flag.

    hollistech has a utility, ddkbuild, which allows you to create a ddk build window within VS, you can download it from


  34. edmaster says:

    Thanks for link. I’m not sure that MS VS team will agree with you. Build command line in my case is (global paths for understanding):

       @call "C:WinDDK5600binsetenv.bat" C:WinDDK5600 fre WXP

       cd C:Projects<solution name><project name>


    It works fine!

  35. doronh says:

    frankly, it doesn’t matter what the VS team thinks b/c the WDK/DDK is not their product.  The policy of not supporting drivers built in VS comes from the WDK/DDK team.  furthermore, if you ever want MSFT product support for a driver issue, it needs to be built in the WDK/DDK.


  36. edmaster says:

    Thanks for your answer! I’m not professional in this area. I use VS Studio 2003 environment for writing source code of kernel mode driver and working with VSS. For building I use WDK (last line in build action: C:WinDDK5600binx86build.exe). For debugging I will use WinDbg and others tools from "Debugging tools for Windows" package. Is this way not good practice? Can you explain me your point?

  37. doronh says:

    using windbg is good.  my point is that the WDK/DDK team supports a very narrow view of how things should be built and that it must be from a DDK build env and not something cobbled together in VS.  If you can get VS to use the DDK build env wholesale, great.  personally, i would just use ddkbuild from b/c someone (and alot of the community) has invested alot more time then I would be willing to put into such an effort.


  38. dispensa says:

    I have a Very Important Question for you:

    How do you pronounce your name?

    I just watched Nar’s Channel9 video and the guy asking the questions was saying it one way while Nar was saying it another. Neither of them match what I thought I heard you say last year at the MVP summit.

    Thanks. 🙂


  39. richt says:

    Hi, I’m new to driver writing – at least, not written one since OS/2 🙂 – and I’m hoping you can help. Sorry if this is a dumb question.

    I’m writing a lower filter driver for a joystick using the HIDclass stack, to intercept IOCTL_INTERNAL_USB_SUBMIT_URB packets and tweak them on the way through.

    I’m having a problem with a very simple completion routine for EvtIoInternalDeviceControl – atm it’s not even trying to write the data, it just calls DbgPrint followed by

    WdfRequestCompleteWithInformation(Request, CompletionParams->IoStatus.Status, CompletionParams->IoStatus.Information); The dispatch routine currently processes URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE and sets up the completion routine.

    Here’s the problem: if the completion routine is not set up (commented out) then the driver loads OK and InternalDeviceControl packets get passed through, and I can see them in DebugView, beginning with 3 GetDescriptorFromDevice packets. However, if I uncomment the call to WdfRequestSetCompletionRoutine, then the completion callback is invoked (this is traced in DebugView), but my driver only gets 2 GetDescriptorFromDevice packets, then all trace output stops, and I have to unplug the joystick. I’ve tried various incantations around the WdfRequestCompleteWithInformation call, none of which make any difference. If I leave the WdfRequestComplete call out (I’m trying anything!), then the driver just goes quiet and won’t unload when I unplug the joystick. Presumably it’s something to do with what I’m doing in the completion callback.

    How am I supposed to handle request completion routines in a lower filter driver? I’ve looked at all the samples I can find but I’m not getting it. And once I’ve got this working, are there any tricks or gotchas when getting hold of the data buffers and munging the contents, during the callback?

    Thanks, Rich

  40. doronh says:

    what does your dispatch routine look like?  are you calling WdfRequestFormatRequestUsingCurrentType() before calling WdfRequestSend?  You need to format the next stack location if you are going set a completion routine (that is a WDM rule that leaks into KMDF).


  41. richt says:


    Thanks for your suggestion – that call seems to have done the trick!

    Strangely, none of the samples in %DDK_ROOT%srckmdf actually use this call (at least, a quick grep turns up nothing). Also I was using a filter sample from OSR (, and although the Web page text specifically mentions this routine, unfortunately it’s not in the downloaded source! Anyway, you’ve saved me probably days of hair-pulling 🙂

    Now I’m going to try to find the correct incantations to access and modify the buffer on its way back through the completion callback …

    Thanks again,


  42. doronh says:

    since KMDF didn’t format the request using one of its WDFIOTARGET routines, you will need to go into the PIRP to get the resulting buffer, but you will still need to complete the WDFREQUEST using WdfRequestComplete().  Something like this to get the PURB

    PURB urb = (PURB) IoGetCurrentIrpStackLocation(WdfRequestWdmGetIrp(Request))->stack->Parameters.Others.Argument1;

    You don’t see any of the samples making the call to WdfRequestFormatRequestUsingCurrentType() because none of them are filters passing requests down the stack, rather they are completing the requests at their level or sending the requests down the stack and forgetting about them (fire and forget).


  43. richt says:

    That looks like the incantation! I have the source for a WDM driver which I am rewriting, and it does something similar to your code to access the data buffer. I wasn’t sure whether I ought to be trying to use WDF routines instead of IoGetCurrentIrpStackLocation, but you’ve answered my question – thanks once more 🙂

    What you say about the samples makes sense, now I think about the ones I’ve looked at. Maybe there should be a sample that does completion of a forwarded request though – this would seem to be a standard use of a filter driver. Or maybe I’m doing something unusual as always 🙂

    Thanks for the help you provide on your blog – as a driver newbie I for one really appreciate it, and I’m sure there are others who will learn just by reading this thread.


  44. snoone says:

    The KMDF filter at definitely does call WdfRequestFormatRequestUsingCurrentType when setting a completion routine. Check the function WdfFltrForwardRequestWithCompletion on line 1447 of wdffltr.cpp.

    You sure you have the right source (not sure where else you’d get a different version from, but have to ask)?

  45. richt says:

    Apologies, yes, the call is there in my file too. I don’t know how I missed it as I remember checking specifically before posting. Must have been working too late 🙂

    I guess that WdfRequestFormatRequestUsingCurrentType is the replacement for some WDM call then? Not having used WDM, I probably missed the significance of it when I read the article.


  46. doronh says:

    Also, if you ran your driver under the KMDF verifier (see, it would have broken in on the WdfRequestSend() call because you had not yet formatted the next stack location.


  47. doronh says:

    WdfRequestFormatRequestUsingCurrentType  is the equivalent of IoCopyCurrentIrpStackLocationToNext.

  48. wpeople says:

    I have read your blog for a period of time and

    I get a lot from it. Recently, I made a research

    about the driver for mouse, because I found touchpad

    in some Notbooks that does not have the function

    of scroll bar on the right hand side of touchpad.

    Is it possibile to implement by driver?

    However, I got some Notebooks have the function

    as I described. I am curious about that the issue from


    I get the DDK sample about filter in the stack

    below mouclass and the delta information is

    sent through a function callback, called the

    service callback via an array of PMOUSE_INPUT_DATA

    elements. The upper is what I do right now. Do I

    in right path to do that?

  49. doronh says:

    Yes, you are in the right spot, but I don’t think you will be able to get the data you want.  You can get delta information (E.g. the mouse moved 10 mickeys to the right), but from a filter you cannot get the position of the finger on the touchpad.  The ability to use the touchpad’s side as a scrolling surface is custom to the hardware and the vendor’s (ALPS or Synaptics most likely) driver knows how to get this custom data.  A mouse filter driver does not have access to such data.


  50. wpeople says:

    O. Thanks

    Today, I got the notebook that has the function of scrolling on the right side of touchpad. I modified filter driver in PMOUSE_INPUT_DATA of service call back to converse up and down functions. I failed. Could you help about that?

  51. doronh says:

    Like I said previosuly, you do not have enough context in the filter driver to know *where* on the touchpad the user is touching it. All you have in the mouse filter driver is X and Y delta information, not absolute positioning.  You cannot do this from a filter, you must have access to the cumstom data that is only available to the manufacturer of the mouse to know where the user is touching the pad.


  52. tiwari_sanjeev says:

    The ports class installer sample code included with the driver developement kits does not have details about installing the parallel port. It uses ERROR_DI_DO_DEFAULT.

    Is there a specific reason for not providing this code in the sample.

    How is the LPT number decided by the MSports.dll. We have COMDB for serial ports from where we can find which COM ports are free. I don’t see anything similar to COMDB for a parallel port.

    If there is no parallel port in the system and I add a pci card with parallel port. MSPorts.dll always makes it LPT3. I want to make it LPT1 by default (if there is no parallel port in the system).

    how can this be done with out breaking any other functionality.

    If you have any pointer to this please let me know.


  53. doronh says:

    It is based on 2 things

    1)  the name the BIOS assigned to the device

    2)  the resources assigned to the device for the well known resources for LPT1 and LPT2

    since your card has neither of these going for it, the CI picks LPT3.  I guess you could write a device coinstaller and change the setting in the post device install path, although I have never done that so I don’t know how affective it will be.  If it does work, you will have to detect other LPT ports on the machine (HKEY_LOCAL_MACHINEHARDWAREDEVICEMAPPARALLEL PORTS will give you the currently running ports) to avoid a name conflict.


  54. suhetao says:

       hi,i am a chinese boy which  wanna write a file system filter driver for encrypting the folders in windows system.i wrote a win32 application to get which folders that i wanna encrypt, then communicates with the kernel filter driver to notify which folders should be encrypted!

       if there is any accessing with these folders such as double_click the folders to open it,the driver heads off and pauses the IRP transfering , i finish this job in IRP_MJ_CREATE dispatch routines,then notifies the application to pop-up a dialog asking the right password with a textbox control.if it’s the right password that call IoCopyCurrentIrpStackLocationToNext routine copies the IRP stack parameters from the current I/O stack location to the stack location of the next-lower driver so that the folder can be opened!

       now , i get a difficult problem!in windos system, if i click the folder ,then windows’s desktop application called "explorer" will occur many ZwCreateFile event with other application so that many IRP with IRP_MJ_CREATE happened , then the dialog will be pop-up many times whether the password is right or wrong.

       how to solve this problem,thx!

  55. doronh says:

    suheto, I think that design of asking for the password everytime is probably not the right approach to take.  ideally you would want to ask it the first time adn then associate the authentication status of the current user with the correct password so that when the user opens another folder requiring the same password it is done silently.


  56. suhetao says:

    the folder need to be encrypted that is decide in the win32 app!i use the SHBrowseForFolder and SHGetPathFromIDList routine of win32api to get the path of directory which the users wanna encrypt!when the app starts , the app dynamic loads the filter driver and communicates with the file filter driver to told it which FO(File_Object) us care!some part of the source base on IFS with DDK.

    [Code removed -Doron]

  57. suhetao says:

       sorry for i didn’t catch your mind in previous.and sorry for make you in trouble again! i’m so sorry!

       …if you use a thing and you don’t know how it works,it’s actuality not  too wise.this is my motto!in China. it’s short for the information of file system filter driver.chinese can find lew useful information about the development of file system filter at all!

       can you introuduce some books or information about file system filter to me?thank you unfeignedly!

       and  i wanna ask another question. how to create a thread in kernel driver?using which routine and how to achieve?

  58. doronh says:

    to create a thread, you can call PsCreateSystemThread…but having a dedicated driver thread is not usually the answer either.  for short lived work, you can use work items (IoAllocateWorkItem/IoQueueWorkItem)


  59. suhetao says:

    dear doronh. as you say previously!

    suheto, I think that design of asking for the password everytime is probably not the right approach to take.  ideally you would want to ask it the first time adn then associate the authentication status of the current user with the correct password so that when the user opens another folder requiring the same password it is done silently.

    I think you means that I need to have a kind of mechanism to track all files or folders of the current user or maybe even current process to determin if they got authenticated or denied.

    And authentication always comes with authorization. That’s why you mentioned "same password".

    is it right?but how to make it out?can you talk me more information!

    please  🙂

  60. apraveen says:

    Hi Doran,

    KMDF document clearly states that KMDF takes care of processing of


    The driver need not process Power IRPs unless they need to perform any

    special functions in handling hardware etc..

    I have got a driver for BD which is KMDF based that enumerates child

    devices which are NDIS drivers (ethernet controllers).

    When the system wakes up, apart from writing proper power state into a

    hardware device register,

    driver needs to program some volatile hardware registers to correct


    basically to ensure that they

    remain programmed properly when they come out of sleep state.

    The KMDF Document talks about the following event callbacks.



               EvtDeviceD0 Entry







    Can you let me know which are the callback functions that I need to

    implement and which one should I use

    to basically program hardware registers with its correct values?

    As I said earlier, I am facing "Power IRP" not completion problem and not sure where the problem is.


  61. apraveen says:

    With KMDF I assume that the driver no longer needs to call

    PoSetPowerState() to inform the Powermanage of the fact

    that device is entering lower power state.

    Please correct me if this assumption is wrong.

    The reason for this question is that I have not registered any

    evtcallback when the system goes to lower-powerstate either

    ebcause of shutdown/sleep state. But I am seeing a crash

    saying that


    A driver is causing an inconsistent power state.


    Arg1: 00000003, A device object has been blocking an Irp for too long a time

    Arg2: 82b48b98, Physical Device Object of the stack

    Arg3: 8330fbe0, Functional Device Object of the stack

    Arg4: 83432900, The blocked IRP

    kd> !irp 83432900

    Irp is active with 4 stacks 3 is current (= 0x834329b8)

    No Mdl Thread 00000000:  Irp stack trace.  

        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

    >[ 16, 2]   0 e1 8330fbe0 00000000 8183beb7-918e2238 Success Error Cancel pending

          Driver<xyz> nt!PopRequestCompletion

    Args: 00016600 00000001 00000004 00000005

    [  0, 0]   0  0 00000000 00000000 00000000-918e2238    

    Args: 00000000 00000000 00000000 00000000

    Wondering whether this is a Power IRP and whether it has something

    to do with not handling power-pnp IRPs.

    Appreciate your insights into this problem.



  62. darwine says:


    I am working on a WDF Miniport Driver for a wireless broad-band ethernet adapter that is in a PC-Card configuration.  I have a problem with the Driver NOT Unloading.

    We are using NDIS 5.1 for Power / PNP / MiniportQueryInformation / MiniportSetInformation.  The driver returns NdisMediaStateDisconnected when queried for OID_GEN_MEDIA_CONNECT_STATUS.  We have a limited set of Custom OIDs that we use for communicating to the driver and/or device.  We use these Custom OIDs during manufacturing, to tune certain parameters of the hardware.  We are allocating 2 memory spaces into the PC-Card that are accessed through these custom OIDs.

    The driver will fail to unload (via a surprise removal) after many writes are performed to both memory spaces.  The driver will receive the halt event after the surprise removal, but not the unload event.  The unload event will occur only after the application has closed.  But, if we run a test that makes many writes to only 1 of the memory spaces (doesn’t matter which), the driver WILL unload via a surprise removal.

    Also, if the application closes the handle to the driver after the many writes to both memory spaces and we issue a ‘Safely Remove Hardware’ to stop the driver, Windows responds with "The device ‘xxx’ cannot be stopped because a program is still accessing it".

    The application that is creating a handle to the driver is built from Borland Builder 6.  The functions used to create/close the handle is CreateFile()/CloseHandle().  The queries are sent using DeviceIoControl(hf, IOCTL_NDIS_QUERY_GLOBAL_STATS, …).

    The functions / macros used by the driver are -> READ_REGISTER_ULONG / WRITE_REGISTER_ULONG / WRITE_REGISTER_BUFFER_ULONG.

    Any ideas on where to look for a solution would be greatly appreciated.


    Darwin Erickson

  63. doronh says:

    praveen, you no longer have to call PoSetPowerState. This bugcheck is not caused by not calling this API.  It caused by a power irp being stuck in the stack.  In a KMDF driver, this can be caused by synchronously waiting in any of the power down callbacks or by not acknowledging in flight I/O thati s in a power managed queue (you will see output in the debugger if the latter is occurring).  

    If you run ‘!devstack <PDO from the stack (arg2)>’ you can see which stack is stuck since the output of !irp isn’t giving you any clues.  In short, this is a driver bug somewhere because something is blocked, not because you didn’t call a WDM API.


  64. apraveen says:


    kd> !devstack 0x82b48b98

     !DevObj   !DrvObj            !DevExt   ObjectName

     8330fbe0  Driver<xyz>     830c7d18  

     82b4ef18  DriverACPI       838aca60  

    > 82b48b98  Driverpci        82b48c50  NTPNP_PCI0007

    !DevNode 82b54be8 :

     DeviceInst is “PCIVEN_10DE&DEV_0450&SUBSYS_CB8410DE&REV_A13&2411e6fe&0&30”

     ServiceName is “<xyz>”

    This is all the information I get from “devstack” o/p.

    Can you pls let me know how to figure out whether the problem is not completing in-flight I/O or driver stuck synchronously waiting in a power down callback. I know for sure that its not latter becuse, I do not have any callback registered while the device goes to lower-power state.

    From your explanation it looks like I am not completing some other IRP (not a Power-IRP though). If thats the case, how do I ensure that in-flight IRP is completed given the fact that I do not have any callbacks.

    Will KMDF not take care of sending any new IRPs once Power-down IRP has been processed and also waiting for already sending IRPs to be completed before taking a device to lower power?

    But is it not true that KMDF takes care of seeing to that no new requests are delivered to the driver after it has entered low state.

    Following is that I see in KMDF Document:

    Also by default, KMDF handles power management for I/O queues, and each I/O queue inherits the power state of its associated device. During Plug and Play or power state transitions and any time the device is not in the working state, KMDF queues incoming I/O requests but does not dispatch them to the driver. Therefore, if the driver creates its queues before the device enters D0, the queues are in the WDF_IO_QUEUE_STOPPED state, and KMDF queues any I/O requests targeted at the device. When the device enters the working state, KMDF resumes presenting requests. A driver can change this default when it configures each queue by setting the PowerManaged field of the configuration structure to FALSE.

    A driver can also specify whether a queue accepts I/O requests that have a zero-length buffer. By default, KMDF does not dispatch such requests to the driver; instead, it completes them with STATUS_SUCCESS.

    BTW, I am using default settings for “powermanaged” and “AllowZeroLengthRequests ” and did not make any changes to them

    Thanks a lot for your help,


  65. doronh says:

    Are you the FDO for stack?  Then by default you are using power managed queues.  What I am saying is that when we power down, a power managed queue will block any new I/O from coming in as well as *wait* for all I/O that has already been presented to the driver to either be completed (by calling WdfRequestComplete) or acknowledged (by calling WdfRequestStopAcknowledge() in your EvtIoStop routine).

    I think what is happening is that you have existing in flight I/O in your power managed queue and we are waiting for you to acknowledge those requests.  The power managed queue will print to the debugger and that KMDF log that it is waiting (once a minute or every 30 seconds, can’t remember).  If you are on Vista (which i think you are), the debugger output is off by default.  To turn it on, execute ‘ed nt!Kd_DEFAULT_Mask 0xFFFFFFFF’ in the debugger.  !wdflogdump will show you the KMDF log.

  66. doronh says:

    To program your device when it is coming out of low power, you should register a EvtDeviceD0Entry callback and program it there.  This will also be called when your device is initially powered up as well (e.g. a pnp start).  Now the question becomes which device do you assign the callback to.  If it is for the the entire device, register it on the FDO. If it is for a specific PDO, register it on the PDO…but if you need to serialize access to the registers and only one PDO can touch the registers at a time, you want to consider registering the callback on the FDO and initializing it there so there is no contention.

    If you have a hardware based interrupt and you are using a WDFINTERRUPT, you might want to use EvtDeviceD0EntryPostInterruptsEnabled if you need to do your register initialization using your interrupt.


  67. apraveen says:

    Hi Doron,

    “I think what is happening is that you have existing in flight I/O in your power managed queue and we are waiting for you to acknowledge those requests.”

    What do you mean by inflight I/O requests? Requests can be categorized for this purpose into four types:

    1. Requests that are going to come after device had been put to low-power state.

    2. Requests that came before device was put to low-power state and is being processed by kmdf driver or driver below in the stack but not yet completed.

    3. Requests that are present in the queue already but not yet processed by driver, when request to put device into lower-powerstate arrived.  If I understand you correctly, KMDF takes care of  request type #1 and #2.

    By In-flight I/O are you referring to I/O requests of type #3?  If so, how do I clear all the I/O requests lying in my queue without processing them when I receive PnP goto lower power event to be processed.  Infact I dont have any evt callback currently set that gets executed when I enter lower-power state. Does that mean I have to register a callback so that I can set a flag whereby all new I/O requests or inflight I/O requests will be cleared/completed/cancelled.

    How do I get current PowerState of my device from KMDF? Does KMDF provide a call by which driver can figure out current powerstate from any of its routines?

    WDF_DEVICE_PNP_STATE WdfDeviceGetDevicePnpState(IN WDFDEVICE Device);

    I see this ruotine, but not sure which value in enumeration WDF_DEVICE_PNP_STATE maps to device in “low power state – but started”?

    Thanks in advance,


  68. apraveen says:

    Hi Doron,

    I completed the IRP requests from withing EvtIoStop.

    Now I dont see the crash. But I face another problem.

    1.  Is there a way to cancel the IRPs that were pending when EvtIoStop() got called?

    2. Will calling WdfRequestStopAcknowledge() from within EvtIoStop() allow me to continue IRP processing to a later point when I wakeup.



  69. doronh says:

    In flight i/o is number 2…requests that have been presented to the driver but not yet completed.  Any requests in the queue that have not yet been presented are not in flight.  

    i don’t understand what you mean by cancel the irps that were pending when EvtIoStop was called.  do you mean that you want KMDF to complete them for you?  you either need to acknowledge them or complete them.  Yes, if you acknowledge them from within EvtIoStop, you can continue irp processing later when you wake up.

    > I see this ruotine, but not sure which value in enumeration WDF_DEVICE_PNP_STATE maps to device in "low power state – but started

    No such state is exposed.  KMDF handles this for you.  KMDF tracks the state, you just process the state change callbacks appopriately.


  70. VelcroILean says:

    Hi Doron,

    When I unplug my USB receiver in the midst of a series of application calls to DeviceIoControl (with a valid handle to my device), the IOCTLs that normally succeed while the receiver is plugged in begin failing (to be expected) and GetLastError() returns ERROR_BAD_COMMAND.  

    While it seems reasonable that if the device is disconnected, that the framework (without the help of the KMDF filter driver) would not recognize the IOCTL,  I’ve not yet found a place in the documentation that tells me to expect ERROR_BAD_COMMAND in that scenario.

    Is ERROR_BAD_COMMAND to be expected for some period of time while the software removal process is in progress?


  71. doronh says:

    It is in the docs, but not in the form you expect it.  WdfIoQueuePurge,, tells you that any new requests that are put into a purged WDFQUEUE will be completed with STATUS_INVALID_DEVICE_STATE.  Power managed WDFQUEUEs are purged when the device is surprise removed.   STATUS_INVALID_DEVICE_STATE resolves to ERROR_BAD_COMMAND in user mode.

    So, to answer the question, yes, it is to be expected that pended i/o and any i/o that are in flight right around the time of the surprise removal will fail with error and can arrive with error before the app is notified that the device has been surprise removed.


  72. apraveen says:

    Is it possible  to find from within a driver, all the in-flight requests that has not yet been completed by the driver?



  73. doronh says:

    Short answer, no…but that is what EvtIoStop is for.  If you need to act on active requests outside of that, then you need to track it yourself.  Why do you need the current list at any given point in time?  in the debugger, !wdfqueue will give you the list of inflight i/o.

  74. apraveen says:

    Needed that info for debugging purposes.  BTW, is there a way I can figure out from PDEvtIoStop, whether we are entering a low-power state or whether the driver is getting disabled/uninstalled? The purpose is to take appropriate action accordingly, ie, if the driver is going to low-power state, I would like to acknowledge inflight i/o to resume it later when device returns to D0. If the device is getting disabled, would like to complete requests with cancelled status.

    When will OS/framework call cancellation routine registered for an IRP? Under what conditions?



  75. doronh says:

    I suggest you read the documentation on EvtIoStop,  From there you can answer your own question as to how to determine if it is a power down or remove.

    The framework will not explictily call the cancelation routine of a request on its own.  The sender of the request will have to cancel the request first.

  76. apraveen says:

    Thanks d for the link. It answer my question.  BTW, cancel routine is getting called. I think this is because the app which sent these IRPs is closing itself or explicitly calling the cancel request. Not sure which of this is happening.  The problem I am facing is that PDEvtIoStop is not getting called for some reason. When I try to disable the driver, the app which is having either some handle or some other reference, gets to know this and tries to cancel the requests – I guess.  But not all the cancel requests go through successfully. This is resulting in the operation of disabling my device to fail and also PDEvtIoStop is not getting called.

    Does this explanation sound possible?

  77. doronh says:

    Do all of your pended requests have a cancel routine on them?  if not, they will not be canceled.  KMDF is not blocking the remove, something in your driver is not written properly.  !wdfdevicequeues <WDFDEVICE> will give you the list of oustanding requests.  you should run it after you get into this state where a query remove failed.  EvtIoStop is called in the remove path itself (among many other paths, it is also called in surprise remove for instance) so to get to the graceful remove state, you need to properly handle cancelation in any pended requests in your driver.

  78. apraveen says:

    Hi Doron,

    Regd the post "Another Server 2003 SP1 DDK link"-

    that points to following link:

    Where can I get the SP1 DDK with KMDF bits?

    Does the link mentioned in the above post of yours

    contain wdf01000.tmf file?

    If not, can you point me to link from where I can get ddk with the

    above tmf file?

    Not able to execute !wdfqueue or any !wdf*** commands w/o tmf file.



  79. doronh says:

    Darwin, if a device is surprise removed, it will not move into the removed state until all open file handles have been closed.  This is why you do not see an unload until your application closes the handle.  As for the case where you close the handle and Windows still fails the graceful remove, could it be that your driver still has I/O (in the form of OIDs?) pended and that the file handle is not really closed?  When you close a file handle, the outstanding I/O on the handle is canceled, but not necessarily completed.  You could turn on setupapi logging ( and see if that gives you a better indicatio of what is going on.


  80. apraveen says:

    Thanks D. Will turn on setupapi logging and see whats happening. But in the past, setupapi logging never gave much details for eg. like who is holding or what is blocking driver unload. All it would say is that “device install” failed or PROB_START_FAILED/PROB_LOAD_FAILED – not remember which one. Will try my luck this time.

  81. apraveen says:

    Regarding setupapi logging, by default I see that logging level specified by registry entry HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionSetupLogLevel is set to max level of 0x2000ffff. The last 2 bytes are set to 0xffff. I have always seen this to be the case by default. But apart from the mesg:

    “Device required reboot: Could not disable device”.

    There is no other indiciatino of why device cannot be disabled.

  82. doronh says:

    Well, there is not much else I can suggest.  You can start removing functionality / running applications / scenarios until the disable succeeds and then start adding them back and seeing when the failure shows up again.  This will give you a more narrow window to investigate.

  83. darwine says:


    > As for the case where you close the handle and Windows still

    > fails the graceful remove, could it be that your driver still has I/O

    > (in the form of OIDs?) pended and that the file handle is not really > closed?

    I have been testing this.  The app does receive all I/O (this is handled synchronously).  Also, when the app closes the handle, there is no I/O being transferred.

    Setupapi logging did not shed any light on the problem.

    Our solution for now is to open a handle to the driver before each I/O, then close the handle when completed.  We had to save the registry path to the driver after the 1st open, to save time during the following I/O’s.



  84. talzur says:


    I would like to know if it is possible that a driver would handle several devices interrupts simultaneously.

    Lets say that I have writen a driver for a PCI board which holds several DSPs. The board itself and also each and every one of the DSPs are identified by the OS has a PCI devices. I wish to address a certain DSP only if it has generated an interrupt, is it possible ?, should I do that by calling WdfInterruptCreate in the DioEvtDeviceAdd ?

    Thanks for your help

    Tal Zur

  85. apraveen says:

    Hi Doron,

    I see this mesg when I use bpid command:

    kd> !bpid 0108    

    Finding wininit.exe (0)…

    Waiting for wininit.exe to break.  This can take a couple of minutes…

    Break instruction exception – code 80000003 (first chance)

    Stepping to g_BreakinProcessId check…

    Unable to find g_BreakinProcessId load

    Any idea whats wrong? does it have anything to do with unavailability of user-symbols? I am sure that kernel symbols path is correct. O/p for process 0108 from “!process 0 0” command:

    PROCESS 8ebd3ad8  SessionId: 0  Cid: 0108    Peb: 7ffd5000  ParentCid: 021c

       DirBase: 0e2e73e0  ObjectTable: 96123e48  HandleCount:  95.

       Image: nSvcIp.exe

    I tried reloading symbols, it still did not work. Neither did .process /i <process name>.  Any idea whats going wrong?



  86. doronh says:

    Tal, it sounds like each DSP is showing up as a separate PCI function.  Is that correct?  There are N devices in device manager that correspond to your single device?  If so, each device can address its own interrupt, but you cannot easily share the interrupts across devices.  If all of your DSPs are a part of one PCI function, you can easily use any of the interrupts assigned to your device since there are no sharing issues across different device stacks.

    You create WDFINTERRUPTs in your EvtDriverDeviceAdd routine, see the plx example in the WDK.  You can create as many WDFINTERRUPTs as you think you will need.  If there are fewer interrupts assigned to your device, the extra WDFINTERRUPTs remain unused without error.

    If you can clarify how your device is enumerated, then i can help further if this is not enough.


  87. doronh says:

    praveen, you need user mode symbols for the NT user mode DLLs.  are you using the public symbol server and do you have symbols for these DLLs (like kernel32, user32, etc)?

  88. apraveen says:

    I have a crash. (I forgot to set kd_DEFAULT_MASK 0xff). I want to look at the queue for my device object. I have the following information from the crash dump. It shows two Power Irps pending. No other IRP is pending.

    Is it possible to find what exactly is the handle that I am holding on to. Is it file handle or what could it be that my driver is holding. Sorry, if I am repeating this question again. Is there a way to figure it out from the dump? Is there scope for probing the dump further to get any hints from OS on what could be the problem?

    [ed:  debugger log removed]

    kd> !WDFDEVICE 0x7b7f84a8
    Dumping WDFDEVICE 0x7b7f84a8
    WDM PDEVICE_OBJECTs:self 84802490, attached 8339e6d8, pdo 82f94030
    Pnp state:  119 ( WdfDevStatePnpStarted )
    Power state:  31a ( WdfDevStatePowerGotoDx )
    Power Pol state:  52a ( WdfDevStatePwrPolSleepingWakePowerDown )
    Default WDFIOTARGET: 7b7fdc48
    Pended device power irp 9ffa6f00
    Pended system power irp 9f2b4f00
    Device is the power policy owner for the stack
    kd> !wdfkd.wdfdevicequeues  0x7b7f84a8
    Dumping queues of WDFDEVICE 0x7b7f84a8
    Number of queues: 1
    Queue: 1 (!wdfqueue 0x7b7f86a8)
       Parallel, Power-managed, PowerStoppingDriverNotified, Can accept, Can dispatch, ExecutionLevelDispatch, SynchronizationScopeNone
       Number of driver owned requests: 2
       Power transition in progress
       Number of waiting requests: 0
       Number of requests notified about power change: 2
               !WDFREQUEST 0x6b4580c8  !IRP 0x97142f20
               !WDFREQUEST 0x6adc79c8  !IRP 0x9717ef20
       EvtIoDeviceControl: (0x87afb802) nvnwbx32!PDEvtIoDeviceControl




  89. apraveen says:

    Unless a device has task related to arming/disarming wakeup signal it need not register a EvtCallback funtions for either arm/disarm functions incase of a KMDF driver.  The reason is that this was not the case with previous WDM wherein the bus-driver(PDO) need to pend IRP from top and inturn send a IRP down if required. Also a Bus-Driver needs to keep track of no. of child-devices and IRPs it received from child devices and increase/decrease the Wait_WAKE IRP count accordingly and send a IRP down if required.. All this painful stuff is not required anymore with KMDF as long as the driver (PDO/FDO) does not have to do any device specific arming/disarming operations.

    Is my understanding correct?


  90. apraveen says:

    Yes. I am using the public symbol server only.



  91. Ted Lin says:

    Hi, Doron,

    I write a software driver and install it to Vista RC2. The below is catched from the The driver work well. But the device ICON is shown a question symbol. If I install the same driver to WinXP sp2 or Win2K3, the ICON is well. Does something wrong in the ICON registry?




    >>>  Section start 2002/01/01 00:08:21.328

         cmd: “C:Windowssystem32mmc.exe” “C:Windowssystem32CompMgmt.msc”

        dvi: No class installer for ‘WDF Gsensor Driver’

        dvi: Using exported function ‘WdfCoInstaller’ in module ‘C:Windowssystem32wdfcoinstaller01005.dll’.

        dvi: CoInstaller 1 == wdfcoinstaller01005.dll,WdfCoInstaller

        dvi: CoInstaller 1: Enter 00:08:21.343

        dvi: CoInstaller 1: Exit

        dvi: Default installer: Enter 00:08:21.343

        dvi: Default installer: Exit

    <<<  Section end 2002/01/01 00:08:21.343

    <<<  [Exit status: SUCCESS (DI_DO_DEFAULT)]

  92. apraveen says:

    Hi Doron,

    When I execute:

    kd> !wdfkd.wdfqueue  0x7cc5f290

    I see a line:

       Number of requests notified about power change.

    Power change notification is done by framework invoking

    PDEvtIoStop() right?



  93. gadit says:


    I would like to develop a USB KMDF-based driver.

    Before I start with the coding of the driver, I would like to know if the current KMDF version (which is based on the current WDM version) is stable enough and will work properly with Vista?

    I’m also intersted in doing a courseseminar in the subject.

    I saw on the web that Hilf!Gmbh (a german company)are doing a KMDF course, in cooperation with Datronic (a company from Portugal).

    I would like to know if you have heard about these companies, are their courses reliable?

    (OSR does not have a KMDF in the nearby future).



  94. apraveen says:

    Dont see a evt callback fn for processing IRP_MN_CANCEL_REMOVE_DEVICE.

    Is it not reqd with kmdf? Does framework make this obsolete?



  95. doronh says:

    ted, I asked Jim Cavaliaris of the device management dev team and he said:

    In the ClassInstall32 AddReg of the INF below, an icon is specified that doesn’t actually exist.  It can’t be loaded, so the unknown icon is shown instead.

    specifically – the icon index is positive (HKR,,Icon,,2), which means it should come from the class installer or property page provider DLLs, but neither of those is added for this class.

    Such a class-specific add-registry section has the following general form:



    The system uses the specified icon to represent your installer to the user.

    If the Icon value is positive, it represents a resource identifier for a resource. The resource will be extracted from the class installer DLL, if the Installer32 key is specified, or from the property page DLL, if the EnumPropPages32 key is specified. The value “0” represents the first icon in the DLL. The value “1” is reserved.

    If the Icon value is negative, the absolute value represents a predefined icon. See SetupDiDrawMiniIcon for a list of the predefined icons. For example, “-18” specifies the “Unknown” icon (18).

  96. doronh says:

    praveen, let’s answer all of these at once.

    the output of !wdfqueue is telling you about the requests you are holding onto that the queue is waiting to be acknowledged or completed.  These requests will be (or have been) pased to EvtIoStop.  

      Number of requests notified about power change: 2

              !WDFREQUEST 0x6b4580c8  !IRP 0x97142f20

              !WDFREQUEST 0x6adc79c8  !IRP 0x9717ef20

    i terms of wake, are you asking if the framework automatically propagates a wait wake irp from a PDO down the FDOs stack when the PDO is armed?  Currently KMDF does *not* do this, although it is a feature we are planning to implement in the future.  You can implmement this on your own by registering for EvtDeviceArm/DisarmForWakeAtBus in the PDO and maintain a count.  On arm you interlock increment it, on disarm you interlock decrement it. when the count goes from 0->1, call WdfDeviceAssignSxWakeSettings on the FDO passing WdfTrue for the state and when it goes 1->0, pass WdfFalse.

    > Dont see a evt callback fn for processing IRP_MN_CANCEL_REMOVE_DEVICE.

    That is correct, KMDF handles the state transitions as well.  If you look at EvtDeviceQueryRemove() (and Stop() for that matter) you can just return a yes/no answer as to whether the query will succeed or not, you should not be changing state in that callback.  Furthermore, you should rarely need to register for EvtDeviceQueryRemove to begin with.  If you want to block query remove or stop you can call WdfDeviceSetStaticStopRemove,

  97. doronh says:

    Gadi, KMDF v1.5 (available in the WDK and shipping in Vista) is stable.  As it ships in Vista and there in box Vista drivers using it, I would say it works properly on Vista ;).  Sorry, I don’t know about anybody’s courseware.  What I can tell you is that nobody has asked us to review anything for correctness :).


  98. Ted Lin says:

    Dear Doron,

    Thanks for your help.  As you said, the specific icon does not exist. So I try to add my driver to system class and ignore the icon assign. Then it will show the system device icon well.  But I try to write some Setup APIs in my device driver to show my private icon. I never do success. I search the samples of the Setup APIs.  But I cannot find anything in DDK and SDK, even in the internet. Could you lead me to find some samples of the Setup APIs about the private icon?



  99. doronh says:

    Ted, are you the resource identifier for the icon is 2 (and not "2") in your DLL?  By default Visual Studio will pick the next available number, you either have to change the resource identifier for the icon to 2 or change the INF to refer to the resource identifier VS created for you.  You can view the value in the resource manager or in resource.h for the project.

  100. apraveen says:

    As mentioned in the link below, I enabled trackhandles; Now how do I see the information captured basically the references to objects?

     [ED:  removed !wdfdevice output, not relevant]

  101. doronh says:

    Praveen, the output of !wdfhandle will show you the current reference count.  You should also read this post … but you should never have to worry about these counts unless you add your own reference via WdfObjectReference().    The reference count definitely does *not* play a part in PnP state changes, especially query remove.

    What problem are you trying to solve?

  102. KMDF says:

    Hi, how do we find the cause of assertion failure for KMDF drivers after we turn on the KMDF verifier in Vista’s registry? Are there commands or procedure we can use to find that info? I know OSR has an article on it, but it does not help too much. And during my driver testing, I found the following text from windbg:

    Assertion failure – code c0000420 (first chance)

    nt! ?? ::FNODOBFM::`string’+0x4253:

    fffff800`01836ca0 cd2c            int     2Ch



  103. doronh says:

    an INT 2CH is a NT_ASSERT.  KMDF does not use NT_ASSERT, so this is coming from within the kernel itself.  Can you post a callstack with the correct symbols for NT and wdf01000?  Typically to debug a KMDF breakpoint you will need KMDF symbols and wdfkd.dll to view the KMDF log (


  104. Alex Palka says:

    I have a problem with my USB driver (for BT dongles) under Vista.

    Sometimes I need to send a URB to reset/abort a pipe (by wrapping the URB in an IRP (IRP_MJ_INTERNAL_DEVICE_CONTROL/IOCTL_INTERNAL_USB_SUBMIT_URB) and sending it to the bus driver usbhub). The IRP is sent asynchronously (first allocated with IoAllocateIRP, then freed in the completion routine), because the routine sending it gets called at DISPATCH_LEVEL.

    Everything works fine under XP, but Vista bluescreens at once – here’s the corresponding stack trace from WinDbg:

    818e9974 81a07cce badb0d00 818efac0 84822134 nt!Kei386EoiHelper+0x28ec

    818e9a14 89ca8c53 00220013 8479b028 00000000 nt!IoBuildDeviceIoControlRequest+0x207

    818e9a60 89ca8cbb 84818028 00220013 818e9ab4 usbhub!UsbhSyncSendInternalIoctl+0x3f

    818e9a80 89ca8739 84818028 818e9ab4 00000001 usbhub!UsbhFdoCheckUpstreamConnectionState+0x1a

    818e9ab8 89ca89df 84818028 818e9af0 818e9ae4 usbhub!UsbhSyncSendCommand+0x28

    818e9afc 89ca8b61 84818028 00000001 818e9b24 usbhub!UsbhQueryPortState+0xcc

    818e9b2c 89ca7e86 84818028 83f45130 85944a18 usbhub!UsbhFdoValidateConnectionPdo+0x78

    818e9b4c 89ca813c 848180e0 83f45130 85944a18 usbhub!UsbhFdoUrbPdoFilter+0x87

    818e9b70 89ca7c92 83f45130 85944af4 83f45130 usbhub!UsbhPdoInternalDeviceControl+0xf6

    818e9b84 81867cc9 83f45130 85944a18 8411bbd8 usbhub!UsbhGenDispatch+0x4a

    818e9b9c 88f19334 85a26408 818e9bb8 88f1937a nt!IofCallDriver+0x64

    818e9ba8 88f1937a 8411bb20 833dc1f8 818e9bf4 baracodausb!IsoUsb_SyncSendUsbRequest+0x5c [c:usersalexdesktopstackbaracodaclisyscsrbc_sco.c @ 983]

    As you can see, usbhub.sys calls IoBuildDeviceIoControlRequest, which crashes because the CPU is at DISPATCH_LEVEL at that time. I have put the code in a work item, it works just fine but seems to slow down the driver a bit and some ISO packets get lost. Is there any better way to tackle this problem? Why does the kernel call a function that needs to be run at PASSIVE_LEVEL in response to an IOCTL_INTERNAL_USB_SUBMIT_URB anyway?



  105. doronh says:

    You cannot send all URBs subtypes at DISPATCH_LEVEL.  Specifically, you can send URB_FUNCTION_RESET_PIPE (and i thought abort as well, but the docs don’t say) only at PASSIVE_LEVEL, see  The fact that it worked on XP means you got away with it there ;).  


  106. VelcroILean says:

    When a driver receives and IOCTL that requires an output buffer and the  OutputBufferLength is not large enough to contain the output data,  what  value of status should we pass to

    WdfRequestComplete(Request, status)  ?


  107. doronh says:

    John, great question.  I wrote about how to do this today, see  Sorry it is a little long, I wanted to be thorough 😉


  108. Alex Palka says:

    I have a bus driver (the toaster KDMF example, adapted for my purposes 😉 that manages a virtual bus.

    The devices being created by the bus driver are virtual modems and COM ports. Their FDOs send an IRP to the bus driver (using IRP_MJ_INTERNAL_DEVICE_CONTROL) whenever the corrresponding COM port/modem is being opened  by an application. All the PDO dispatch routine does is to set an event (shared with a user-mode application) residing in the device extension. I use IoAllocateIrp to create the IRP as the thread context is arbitrary.

    Everything works fine for the COM ports because they don’t ever call the PDO INTERNAL_IOCTL dispatch routine at DISPATCH_LEVEL, only at PASSIVE_LEVEL.

    On the other hand, when the modem is being installed, the same routine of the PDO seems sometimes to be called at DISPATCH_LEVEL and I get a blue screen in that case. The problematic function is WdfRequestCompleteWithInformation(Request, status, length);

    Here’s the stack trace:

    f88a6714 804e1745 badb0d00 00000000 8055f214 nt!Kei386EoiHelper+0x2883

    f88a67a4 804e20e7 00000000 8266a280 82bd3248 nt!KeDelayExecutionThread+0x261

    f88a67b8 f8c1771f 8266a280 00000000 00000000 nt!KeSetEvent+0x5e

    f88a67dc f782eba4 81eab10c 7d42cdb0 00000000 baracodabus!Bus_Pdo_EvtIoInternalDeviceControl+0x131 [h:atoasterbusdynamicbuspdo.c @ 524]

    f88a6800 f782ff7c 7dc27cf8 7d42cdb0 00000000 Wdf01000!FxIoQueueIoDeviceControl::Invoke+0x30

    f88a6830 f7832598 7d42cdb0 82bd3248 823d8300 Wdf01000!FxIoQueue::DispatchRequestToDriver+0x445

    f88a684c f7833d2c 823d8300 f7859188 823d8300 Wdf01000!FxIoQueue::DispatchEvents+0x485

    f88a6868 f7834e67 00000000 81eab028 82df28b0 Wdf01000!FxIoQueue::QueueRequest+0x237

    f88a688c f7823d9a 82c22b48 f88a68d4 804e13d9 Wdf01000!FxPkgIo::Dispatch+0x377

    f88a6898 804e13d9 82699f00 82c22b48 81eab0e0 Wdf01000!FxDevice::Dispatch+0x7f

    f88a68d4 804e13d9 81eab028 826d84e0 00000000 nt!IofCallDriver+0x32

    f88a6904 f8af1c51 81eab028 826d84e0 00000001 nt!IofCallDriver+0x32

    f88a6a40 f8af1dd4 8225fd20 826d84e0 826d84f0 Modem!UniOpenStarter+0x48b

    f88a6a5c 804e13d9 8225fc68 826d84e0 826d84e0 Modem!UniOpen+0x50

    f88a6b4c 8056c063 82699f00 00000000 8244b008 nt!IofCallDriver+0x32

    f88a6bc4 8056f2a8 00000000 f88a6c04 00000040 nt!SeDeleteAccessState+0x573

    f88a6c18 8057d2d3 00000000 00000000 8a6d6401 nt!ObOpenObjectByName+0xda

    f88a6c94 8057d3a2 018c951c c0100080 018c94bc nt!FsRtlCurrentBatchOplock+0x2a2

    f88a6cf0 8057d3e5 018c951c c0100080 018c94bc nt!IoCreateFile+0x4f

    f88a6d30 804dd99f 018c951c c0100080 018c94bc nt!NtCreateFile+0x30

    f88a6e0c 8056deaf f88a6d64 0000bbd4 00000000 nt!KiDeliverApc+0xb9e

    f88a6e9c 805731ac e18cae94 f88a6ba4 8000000b nt!ProbeForWrite+0x5be

    f88a6edc 80550146 fffffffc 00000000 0000001c nt!SeAssignSecurity+0x169

    f88a6ee0 fffffffc 00000000 0000001c f88a6ba4 nt!ExAllocatePoolWithTag+0x141

    Could you tell me why WdfRequestCompleteWithInformation somehow causes KeDelayExecutionThread to be called ?


    Alex Palka

  109. apraveen says:

    Hi D,

    When I try to disable my driver in Device Manager, Device Manager

    is hung. I got the following information from !wdflogdump.

    Does the below log from !wdflogdump means

    IRP_MN_QUERY_REMOVE got  completed or is it pending?

    If pending, with whom is the IRP pending?


    110: FxPowerIdleMachine::ProcessEventLocked – WDFDEVICE 0x691CB4C8 !devobj 0x913E6D18 entering power idle state FxIdleInDxStopped from FxIdleInDx

    111: FxPowerIdleMachine::ProcessEventLocked – WDFDEVICE 0x691CB4C8 !devobj 0x913E6D18 entering power idle state FxIdleStopped from FxIdleInDxStopped

    112: FxPkgPnp::PowerPolicyEnterNewState – WDFDEVICE 0x691CB4C8 !devobj 0x913E6D18 entering power policy state WdfDevStatePwrPolStopped from WdfDevStatePwrPolStoppingSendStatus

    113: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x691CB4C8 !devobj 0x913E6D18 entering PnP State WdfDevStatePnpRemovingDisableInterfaces from WdfDevStatePnpQueriedRemoving

    114: FxIoQueue::QueuePurge – All WDFQUEUE 0x68EE21E8 requests cancelled

    115: FxIoQueue::QueuePurge – All driver cancellable requests cancelled  in WDFQUEUE 0x68EE21E8

    116: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x691CB4C8 !devobj 0x913E6D18 entering PnP State WdfDevStatePnpRemoved from WdfDevStatePnpRemovingDisableInterfaces

    117: FxChildList::NotifyDeviceRemove – WDFCHILDLIST 6EC81388:  removing children

    118: FxChildList::NotifyDeviceRemove – WDFCHILDLIST 6D831E28:  removing children

    119: FxChildList::NotifyDeviceRemove – Removing entry 88F8F418, WDFDEVICE 61CC5FE8, PDO 909216B8

    120: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x61CC5FE8 !devobj 0x909216B8 entering PnP State WdfDevStatePnpPdoRemoved from WdfDevStatePnpRemovedPdoWait

    121: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x61CC5FE8 !devobj 0x909216B8 entering PnP State WdfDevStatePnpFinal from WdfDevStatePnpPdoRemoved

    122: FxEventQueue::SetDelayedDeletion – WDFDEVICE 0x61CC5FE8 !devobj 0x909216B8 delaying deletion to outside state machine

    123: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x691CB4C8 !devobj 0x913E6D18 entering PnP State WdfDevStatePnpFdoRemoved from WdfDevStatePnpRemoved

    124: FxIoQueue::Dispose – Purging WDFQUEUE 0x68EE21E8 synchronously

    125: FxIoQueue::QueuePurge – All WDFQUEUE 0x68EE21E8 requests cancelled

    126: FxIoQueue::QueuePurge – All driver cancellable requests cancelled  in WDFQUEUE 0x68EE21E8

    127: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x691CB4C8 !devobj 0x913E6D18 entering PnP State WdfDevStatePnpFinal from WdfDevStatePnpFdoRemoved

    128: FxPkgPnp::_PnpRemoveDevice – WDFDEVICE 691CB4C8, !devobj 913E6D18 waiting for remove event to finish processing

    129: FxPkgPnp::ProcessDelayedDeletion – WDFDEVICE 61CC5FE8, !devobj 909216B8 processing delayed deletion from pnp state machine

    130: FxDevice::Destroy – Deleting !devobj 909216B8, WDFDEVICE 61CC5FE8, attached to !devobj 00000000

    131: FxDevice::Destroy – Deleting !devobj 913E6D18, WDFDEVICE 691CB4C8, attached to !devobj 82BB87E0

    132: FxPkgPnp::Dispatch – WDFDEVICE 0x68E824B8 !devobj 0x91214670, IRP_MJ_PNP, 0x00000001(IRP_MN_QUERY_REMOVE_DEVICE) IRP 0x92622B50

    133: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x68E824B8 !devobj 0x91214670 entering PnP State WdfDevStatePnpQueryRemoveStaticCheck from WdfDevStatePnpStarted

    134: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x68E824B8 !devobj 0x91214670 entering PnP State WdfDevStatePnpQueryRemoveAskDriver from WdfDevStatePnpQueryRemoveStaticCheck

    135: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x68E824B8 !devobj 0x91214670 entering PnP State WdfDevStatePnpQueryRemovePending from WdfDevStatePnpQueryRemoveAskDriver

    136: FxPkgPnp::Dispatch – WDFDEVICE 0x77166C68 !devobj 0x90952DE0, IRP_MJ_PNP, 0x00000001(IRP_MN_QUERY_REMOVE_DEVICE) IRP 0x92622B50

    137: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x77166C68 !devobj 0x90952DE0 entering PnP State WdfDevStatePnpQueryRemoveStaticCheck from WdfDevStatePnpStarted

    138: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x77166C68 !devobj 0x90952DE0 entering PnP State WdfDevStatePnpQueryRemoveAskDriver from WdfDevStatePnpQueryRemoveStaticCheck

    139: FxPkgPnp::PnpEnterNewState – WDFDEVICE 0x77166C68 !devobj 0x90952DE0 e

    kd> !WDFDEVICE 0x77166C68

    Dumping WDFDEVICE 0x77166c68


    WDM PDEVICE_OBJECTs:self 90952de0, attached 82bb88e8, pdo 82bb3700

    Pnp state:  10c ( WdfDevStatePnpQueryRemovePending )

    Power state:  307 ( WdfDevStatePowerD0 )

    Power Pol state:  565 ( WdfDevStatePwrPolStarted )

    Default WDFIOTARGET: 6d83c5b0

    No pended pnp or power irps

    Device is the power policy owner for the stack

    kd> !WDFDEVICE 0x68E824B8

    Dumping WDFDEVICE 0x68e824b8


    WDM PDEVICE_OBJECTs:  self 91214670

    Pnp state:  10c ( WdfDevStatePnpQueryRemovePending )

    Power state:  309 ( WdfDevStatePowerD0BusWakeOwner )

    Power Pol state:  502 ( WdfDevStatePwrPolStartingSucceeded )

    Parent WDFDEVICE 77166c68

    Parent states:

      Pnp state:  10c ( WdfDevStatePnpQueryRemovePending )

      Power state:  307 ( WdfDevStatePowerD0 )

      Power Pol state:  565 ( WdfDevStatePwrPolStarted )

    No pended pnp or power irps

    kd>  !devobj 0x90952DE0

    Device object (90952de0) is for:

     Drivernvnetbus DriverObject 927a3bd8

    Current Irp 00000000 RefCount 0 Type 0000002a Flags 00002004

    DevExt 88e99558 DevObjExt 90952eb0

    ExtensionFlags (0x00000808)  DOE_REMOVE_PROCESSED

                                Unknown flags 0x00000800

    AttachedTo (Lower) 82bb88e8 DriverACPI

    Device queue is not busy.

    kd> !devobj 0x91214670

    Device object (91214670) is for:

    00000077 Drivernvnetbus DriverObject 927a3bd8

    Current Irp 00000000 RefCount 0 Type 00000012 Flags 00003044

    Dacl 849a1d74 DevExt 9717dd08 DevObjExt 91214740 DevNode 9093da20

    ExtensionFlags (0x00000808)  DOE_REMOVE_PROCESSED

                                Unknown flags 0x00000800

    AttachedDevice (Upper) 9e3dc3d0 DriverNVENETFD

    Device queue is not busy.

    kd> !driver DriverNVENETFD

    No export driver found

    kd> !driverobj DriverNVENETFD

    No export driverobj found

    kd> !devobj 0x90952DE0

    Device object (90952de0) is for:

     Drivernvnetbus DriverObject 927a3bd8

    Current Irp 00000000 RefCount 0 Type 0000002a Flags 00002004

    DevExt 88e99558 DevObjExt 90952eb0

    ExtensionFlags (0x00000808)  DOE_REMOVE_PROCESSED

                                Unknown flags 0x00000800

    AttachedTo (Lower) 82bb88e8 DriverACPI

    Device queue is not busy.

    kd> !irp  0x92622B50

    Irp is active with 3 stacks 4 is current (= 0x92622c2c)

    Mdl = 9e36b680 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 82bf2180 00000000 83d9c0ce-926c5f08    

          Drivernvstor CLASSPNP!TransferPktComplete

    Args: 00000000 00000000 00000000 82bf2238

  110. doronh says:

    Alex, are you sure your symbols are correct for ntoskrnl?  KeSetEvent does not call KeDelayExecutionThread in any path.


  111. clay_chang says:

    Hi Doron,

    I am trying to implement a virtual keyboard driver that can inject keystrokes into the system buffer. I implemented it as a HID minidriver. I realized that the driver should be registered with kbdclass in order to receive ioctls like IOCTL_INTERNAL_KEYBOARD_CONNECT (am I right?).

    My question is, how this could be done? Are there anything to specify in the inf file?



  112. doronh says:

    Clay, as a HID minidriver you don’t need to worry about any of this.  You just deal with reporting your HID descriptor and then completing the HID specific I/Os (like get/set report, etc).  By reporting a keyboard top level collection, HIDClass will enumerate a PDO which will have kbdhid and kbdclass loaded on top of it already and you don’t have to write a thing in that stack.

    So, basically, install your HID minidriver with the following in your [Version] section:



    and the rest will be taken care of for you if your HID descriptor reports the right thing.


  113. doronh says:

    Praveen, sorry for the late answer.  The pnp state WdfDevStatePnpQueryRemovePending  means that we have sent the query remove down the stack (or in this case since you are a PDO, completed it).  If KMDF had the pnp irp pended, you would see it in the output of !wdfdevice, it will also tell you if no irp is pending, e.g.

    No pended pnp or power irps

    You can try to run !locks and see who has the pnp lock held and then find the device stack from the callstack of the owner of the lock.


  114. huangwu says:

    Hello doronh:

     I’m a boy whos English is not good enough,but I need your help too.

     Now I’, debugging in a driver project designed for a DAQ card,by using KMDF.

     Now I got a problem and can not continue:My user application hung up @unknow address(at least unknow to me).There is no way I can teminate the application,even if I try to shutdown the machine.

     Here is some codes:

    For the API called by user application:


    For the driver routine that is called by createfile:



       IN WDFDEVICE  Device,

       IN WDFREQUEST  Request,

       IN WDFFILEOBJECT  FileObject



    KdPrint(("ADX:Enter EvtFileCreate And do nothing yet,filename:%xn",WdfFileObjectGetFileName(FileObject)));



    When I track into the API and the driver routine,when I called the createfile API,the driver print out the message into my debugger machine,but then the application hung up and can’t stop any way.I just want to know any possible reason ,can you give me some advices?

    Best wishes . and have a good weekend.

  115. doronh says:

    Huang, you need to complete the create request.



      IN WDFDEVICE  Device,

      IN WDFREQUEST  Request,

      IN WDFFILEOBJECT  FileObject



     KdPrint((“ADX:Enter EvtFileCreate And do nothing yet,filename:%xn”,WdfFileObjectGetFileName(FileObject)));

     WdfRequestComplete(Request, STATUS_SUCCESS);



  116. clay_chang says:

    Hi Doron,

    It’s the virtual keyboard driver again. Now I didn’t go vkbd the HID miniport driver way. Instead I took kbfiltr sample and modify it. I created a control device object to let the client app talk to the device driver via IOCTL.

    Here is how I did it:

    1. Create a device object and attach it to the device stack. Pretty much like kbfiltr.

    2. Intercept the IOCTL_INTERNAL_KEYBOARD_CONNECT to keep the CONNECT_DATA pointer.

    3. Create a control device object. Define a custom IOCTL to let the application talk to the driver.

    4. When client application talks to the driver via IOCTL, I invoke the kept ClassService function pointer to send some KEYBOARD_INPUT_DATA to the stack. (I suppose this step actually inject something to the keyboard buffer, right?)

    No error occurs, but there are nothing happened.

    Here is the code block.

    void SendKey(PDEVICE_OBJECT device)


       devExt->KeyData[0].MakeCode = 0x1e;

       devExt->KeyData[0].Flags = KEY_MAKE;

       devExt->KeyData[1].MakeCode = 0x1e;

       devExt->KeyData[1].Flags = KEY_BREAK;

       irql = KeRaiseIrqlToDpcLevel();

       (*(PSERVICE_CALLBACK_ROUTINE) classService)(







    inputDataConsumed is 2 after the call.



  117. doronh says:

    The problem with the control device is that it doesn’t scale out if you are filtering multiple keyboards.  now you have a 1:N relationship and need to incorporate an addressing scheme into your IOCTLs so that you know how to route which IOCTL to which stack.  Furthermore, the control device is not tied to the pnp state of the stack you are filtering, so you must manually manage this state.  This is why there is a KMDF version of kbfiltr which uses a raw PDO.  Now you have a 1:1 relationship *and* you get the PnP state for free.

    I see a problem with SendKey though.  Why are you storing the data you want to send in a shared buffer (devExt)?  If 2 threads try to make the call at the same time, you will have corrupted data.  Instead, declare a KEYBOARD_INPUT_DATA data[2]; on the stack and then pass the address of the local to the classService callback.

    As for why you are not seeing 0x1E, I don’t know what character that scancode represents.  Try 0x2 (which is ‘1’ on a US keyboard) and see if that works.


  118. Prabhakant says:

    When my driver crashes, I would like to be able to see all the traces right upto the point of the crash. Using WPP tracing mechanism (, I get all the traces that have been flushed to the log file. It seems that there is a way with WinDBG to see traces that were in-memory but not flushed to the file when the crash happened. I have tried using wmitrace dll with WinDBG as explained in this OSR article, but it does not seem to show/dump those in-memory buffer. Would you happen to have the details of how to do it? I will highly appreciate it.

    Thank you.

  119. huangwu says:

    Thks a lot for your help! You are really a good guy.These days the net connection is not very well so I have no chance to login,but it is OK now.

    Thanks once again 🙂 ,happy day ,happy all the days to you.

  120. talzur says:

    Hi Doron,

    I’m writing a driver for a pci board which contains a number of DSP’s on it. Each DSP is identified as a pci device by the OS.

    I would like to give each of the DSP’s a name, which would help me in approaching a specific DSP in order to perform different actions on each of the DSPs (specific action to each of the DSP’s).

    I’m using the WDF function WdfDeviceCreate(…) in order to create a device for each of the DSP’s (I call it from the AddDevice function). In addition I use the function WdfDeviceCreateDeviceInterface(…) in order to give the device a name that would allow me interact with it. If I want to give each of the devices a unique name how can I do so from the AddDevice function ? , is there any information that I can use in order to concatenate it to the device name ? I thought of keeping a global variable that would keep the current number of devices add and to concatenate it to the device name but maybe there is a better way of doing so in the WDF.


  121. doronh says:

    Tal, the device interface will give your device a name.  Each instance of the device interface will be given a unique name by PnP.  Your application would then iterate over all of the instances of the device interface, opening each one.

    Do you want to derive special attributes of the DSP from the name, or you just  want to discover multiple DSPs?


  122. doronh says:

    Prabhakant, great question!  I asked the ETW devs and they gave this advice:

    If your system crashes you should still be able to retrieve the content of ETW trace buffers which haven’t been written out to logfile via wmitrace KD extension.

    list running sessions, so that you can figure out logger id


    set the TMF search path

    !wmitrace.searchpath <TMF Location>

    dump events

    !wmitrace.logdump <LoggerId>  

    Wmitrace is documented in the debugger help


  123. talzur says:


    I just want to discover multiple DSPs and there is no need to derive any special attributes of the DSP from the name.

    I thought of using  WdfDeviceCreateDeviceInterface(…) in order to attach GUID to my device (using NULL as the ReferenceString  parameter for the function).

    Later on in order to use a specific DSP I  have to know the unique name which the OS gave to my device.

    Is using WdfDeviceRetrieveDeviceInterfaceString(…) or IoGetDeviceInterfaces(…) would help me doing so (using the same GUID I used when creating the device interface)?



  124. Prabhakant says:


    When I run the !wmitrace.strdump command, I get 64 lines that say – "Logger Id ….." as shown below. None of these lines show me the name of my log session while the crash happened.

    Is there some other command which will reveal the logger id, or is there a workaround this?

    Thanks a lot.

    kd> !wmitrace.strdump

    (WmiTracing)StrDump Generic

     LoggerContext Array @ 0x80569080 [64 Elements]

       Logger Id  0 @ 0x80569080 Named ”

       Logger Id  1 @ 0x80569084 Named ”

       Logger Id  2 @ 0x80569088 Named ”


       Logger Id 3f @ 0x8056917C Named ”

  125. Sygnosys says:

    Hello Doron,

    I have a few questions somewhat off topic, which are regarding all the stuff related with WPP / ETW. By searching the groups your name keeps coming back associated with ETW and WPP and I haven’t found the guy in “charge” of WPP and ETW in Microsoft, so since you are using it (KMDF), you look like an expert to me on the subject so I hope you can help me.

    I would like to get some information on processing the ETL files in conjunction with TMF files, I searched and I cannot find any information on how to implement this. I use the Tracefmt and Traceview but I need to implement something that fires and event (email, …) when something really bad happens, and since I’m using WPP/ETW I would need this information.

    Additionally I would like to know how can I register my trace provider so that it shows up in the Nonsystem Providers of the Trace Logs Management Console (under Performance Logs and Alerts)

    I would be grateful if you could help on these subjects.


    Cláudio Albuquerque

  126. gaurav_verma says:

    Hi Doronh,

    I am new to device driver programming.I am developing a usb driver.When I call IoSetDeviceInterfaceState(…,TRUE); it is returning Failed status(after starting the device and configuring). I am able to retrieve the symbolic link.Could you please suggest what might be the problem in registering and what all areas I need to recheck.IoRegisterDeviceInterface(called in Add device) is returning STATUS_SUCCESS and returning the correct symbolic link.

    OS : Windows 2003 Server

    using DDK kit for Driver development.

    Thanks nd Regards

    Gaurav Verma

  127. gaurav_verma says:

    Hi doronh,

    I am working on WDM.

    Thanks ad Regards

    Gaurav Verma

  128. doronh says:

    Guarav, any reason why you are not using KMDF?   What type of device driver are you writing (what device class is it in)? This is one of the areas in which KMDF abstracts away the complexity of the problem.  

    What is the specific NTSTATUS value that is being returned from IoSetDeviceInterfaceState?  Are you deregistering the device interface in surprise removal, pls read and


  129. jdh28 says:


    I’m trying to track down an intermittent hang in my application/WDM driver. Using the kernel debugger I’ve narrowed it down to an IRP being sent down the driver stack and getting stuck. Admittedly I’ve only seen it on one machine so far. If I disable hyper-threading the hangs seem to go away. This is under Windows XP SP2.

    Any ideas on what might be the cause or how to track it down further?

    The output from !irp on the IRP in question is (my driver is called


    Irp is active with 3 stacks 2 is current (= 0x86479984)

    Mdl=862a4f88: No System Buffer: Thread 861fb618:  Irp stack trace.

    Flags = 00000900

    ThreadListEntry.Flink = 861fb828

    ThreadListEntry.Blink = 86161b50

    IoStatus.Status = 00000103

    IoStatus.Information = 00000000

    RequestorMode = 00000001

    Cancel = 00

    CancelIrql = 0

    ApcEnvironment = 00

    UserIosb = 00a17ed8

    UserEvent = 00000000

    Overlay.AsynchronousParameters.UserApcRoutine = 7c82bd84

    Overlay.AsynchronousParameters.UserApcContext = 143026f0

    Overlay.AllocationSize = 00000000 – 00000000

    CancelRoutine = f6f2187a   USBPORT!USBPORT_CancelActiveTransferIrp

    UserBuffer = 00000000

    &Tail.Overlay.DeviceQueueEntry = 86479930

    Tail.Overlay.Thread = 861fb618

    Tail.Overlay.AuxiliaryBuffer = 00000000

    Tail.Overlay.ListEntry.Flink = 860dad84

    Tail.Overlay.ListEntry.Blink = 860dad84

    Tail.Overlay.CurrentStackLocation = 86479984

    Tail.Overlay.OriginalFileObject = 863ce588

    Tail.Apc = 00000000

    Tail.CompletionKey = 00000000

        cmd  flg cl Device   File     Completion-Context

    [  0, 0]   0  0 00000000 00000000 00000000-00000000

      Args: 00000000 00000000 00000000 00000000

    >[  f, 0]   0 e1 85d95038 00000000 a7a7ac7c-861be690 Success Error Cancel


           Driverusbehci xjlink!OnReadWriteComplete

      Args: 861be690 00000000 00220003 00000000

    [  3, 0]   0  1 860dac68 863ce588 00000000-00000000    pending


      Args: 00000864 00000000 00000000 00000000



  130. VMan says:


    Our product has several kernel mode drivers – file system drivers, process monitors, network redirectors, etc., because of which installing our product requires a reboot. For Longhorn certification, we need to eliminate reboots. Is there a way to do that? Will porting our drivers to KMDF or any other model help eliminate reboots?


  131. doronh says:

    John, it looks like you are talking the irp the i/o manager presented to your driver and then formatting the next location with a URB and sending it to the usb core.  How do you define hang? the app won’t go away? the irp never completes even though there is i/o for it to fulfill?  If it never completes, are you sure your device is transfering packets over the usb wire?

    do you manually try to cancel the IRP that you sent when the app closes its handle?


  132. doronh says:

    VMan, the driver model itself is not the cause of the reboot.  The inabliity to unload the driver is what requires the reboot.  For some stacks (like the boot or paging storage stack), you cannot remove yourself with out a reboot becase the device stack cannot be torn down.  Which component is requiring the reboot?  all of them?


  133. VMan says:

    Hi Doron,

    Thanks for the quick response.

    One of the drivers we have is a network redirector driver (UNC provider). Right now when we reboot, the OS loads the driver and calls DriverOpen, then the driver registers devices, etc. After installation, if we don’t reboot, how can these drivers be loaded? Who will call DriverOpen?


  134. clay_chang says:

    Hi Doron,

    Is it possible to trigger "Ctrl-Alt-Del" key sequence in a hid keyboard minidriver?


  135. gaurav_verma says:

    hi doronh,

    Regarding IoSetDeviceInterfaceState return value

    I checked the return status

    Its c0000033 ->OBJECT_ NAME_INVALID

    But I checked the UNICODE_STRING and i am passing the same string that i got from IoRegisterDeviceInterface() routine.

    Why is it giving this error?

    Thanks and Regards

    Gaurav Verma

  136. jdh28 says:


    Thanks for your reply. To be honest, the correlation with enabling/disabling hyperthreading had blinded me to the possibility of a problem with our hardware. It seems with further investigation today that the problem lies there.

    To answer your questions, anyway: yes, I am using IRPs in that way. By hang, I mean that the IRP never completes; if I kill the application, then the driver will successfully cancel the IRP.

    I guess that the problem is very timing sensitive, and so disabling hyperthreading just perturbs the timing of requests enough.



  137. sgtyork says:

    I am trying to understand how a USB device is identified when connected to a PC when its device descriptor, iSerialNumber = 0 [no serial number set].  When a serial number  

    is set, it’s fairly straight forward… USBVID_xxxx&PID_yyyyzzzzzzz  where zzzzzzz is the serial number.  Back to the iSerialNumber = 0 case…

    I’d like to tell the user that they have plugged the device into "USB Root Hub, Port 2"  or "Generic USB Hub, Port 1", etc… as per device manager text information [or whatever else is available] because I can’t tell the user that they have plugged device serial number XYZ into the computer – as the device has no unique serial number because iSerialNumber = 0 in the device descriptor.

    It seems that the fabricated serial number has something to do with the port.. for example – I’ve plugged a device with iSerialNumber = 0 into my PC and get the following  


    USBVID_xxxx&PID_yyyy5&5d02db7&0&2      (Top laptop port)

    USBVID_xxxx&PID_yyyy5&5d02db7&0&1      (Bot laptop port)

    USBVID_xxxx&PID_yyyy5&15323D2e&0&1     (laptop replicator port)

    USBVID_xxxx&PID_yyyy6&35d2cc87&0&1     (hub port front left, hub connected to Bot laptop port)

    USBVID_xxxx&PID_yyyy6&23191be2&0&1     (hub port front left, hub connected to Top laptop port)

    USBVID_xxxx&PID_yyyy6&1FAB63CA&0&1     (hub port front left, hub connected to laptop replicator port)

    USBVID_xxxx&PID_yyyy6&1FAB63CA&0&2     (hub port back left, hub connected to laptop replicator port)

    USBVID_xxxx&PID_yyyy6&1FAB63CA&0&4     (hub port back right, hub connected to laptop replicator port)

    [I’m getting the above strings from Device Manager, properties on the selected USB device, details tab, Device Instance Id)

    Can I always count on a&bbbbbbbb&c&d format?

    I notice that the bbbbb file isn’t a fixed length.

    I thought I was getting close when I found…

    Standard USB Identifiers

    but no go…

    This post has lots of fuming on the subject…

    But not really helpful.

    Bottom line.. I’m looking for the rhyme and reason for how 5&5d02db7&0&2 is generated.  The last number seems to be some sort of port indication.  Is there anyway to find  

    out about what hub the device is plugged into from the other data?  How far downstream the device is from the first number?  Etc?  Surely there is an MSDN page somewhere  

    which has what I’m looking for?!

    I’ve found a bit about "The PnP manager assigns a device instance ID to each device node in a system’s device tree." but how do I know what that is?


    Timothy – I can almost no longer see from searching…

  138. doronh says:

    Clay, yes you can send C+A+D from a HID minidriver if you have reported in your HID descriptor that there is a keyboard and push the data up to the keyboard collection.  Did you write a HID minidriver purely to inject a C+A+D?  If so, there are easier ways to do this.


  139. doronh says:

    Guarav, in what context are you calling IoSetDeviceInterfaceState? during start device?  can you send a dump of the interface string?  Did you manually delete any registry keys under HKLM…CurrentControlSetControl or HKLM…CurrentControlSetEnum?

    STATUS_OBJECT_NAME_INVALID is not explicitly returned in the implementation for IoSetDeviceInterfaceState, so I think it might be registry key related.

  140. doronh says:

    John, glad I could get you going on the right track.


  141. doronh says:

    Timothy, the zzzzzz value, or device instance ID, is opaque.  You are not allowed to parse it since its format is private the PnP manager.  It just so happens that the USB hub driver uses the port number as a part of the device instance ID it reports, but how the PnP manager turns that into a unique instance ID is private.

    If a bus driver reports location information, it reports it by handling IRP_MN_QUERY_DEVICE_TEXT/DeviceTextLocationInformation.  If you are interested in this information as a driver, you can query for it.  You can get this string in user mode by calling SetupDiGetDeviceRegistryProperty(SPDRP_LOCATION_INFORMATION)

    Hope that helps.


  142. doronh says:

    VMan, i am not that familiar with the UNC architecture, but have you tried to net stop the driver?  Upon DriverUnload you delete the device objects you created and then when the last references go away, you are unloaded.  at least, that is how NT4 style drivers work.


  143. doronh says:

    VMan, i am not that familiar with the UNC architecture, but have you tried to net stop the driver?  Upon DriverUnload you delete the device objects you created and then when the last references go away, you are unloaded.  at least, that is how NT4 style drivers work.


  144. gaurav_verma says:

    Hi Doronh,

    Yes I manually deleted the keys.Coz after modification in the driver program,I had to again install it. w.ref.t bulkusb installation procedure given in  DDK samples.

    Please suggest how can I correct this problem,and where to search in the registry?

    HKLM/…../enum/USB ->There is a key with VID and PID ,inside  it the instance key is 123456789

    HKLM/…./classes ->There is a key corresponding to USB class,inside it ,0016 key is there which contains driver details

    and in HKLM/…/DeviceClass there is a key corresponding to the guid i have declared

    symbolic link \?USB#Vid_045e&Pid_930a#123456789#{357b9ec8-0e5a-4fb8-aa5b-6701b742d15c}

    Thanks and Regards


  145. gaurav_verma says:

    There is one more key in HKLM/…./DeviceClasses with the entry a5dcbf10-6530-11d2-901f-00c04fb951ed

    which also contains the symbolic name having the same VID ,PID and instance.


    I dont know from where it got generated.

    Thanks and Regards


  146. doronh says:

    Guarav, I hope you learned a valuable lesson here.  Hacking at the registry to uninstall a device will lead to alot more lost time then just uninstalling it correctly (like uninstalling it via device manager or devcon).  

    I would assume that  {a5dcbf10-6530-11d2-901f-00c04fb951ed}

    is your device interface GUID.  You might want to try delete the  a5dcbf10-6530-11d2-901f-00c04fb951ed

    key and then reloading your driver. If that does not work, I would consider reinstalling the OS since you put it the machine into an undefined setup state by touching reg keys that you were not supposed to touch.


  147. gaurav_verma says:

    Hi Doronh,

    If  {a5dcbf10-6530-11d2-901f-00c04fb951ed} is my interface guid,then if I install the original Bulkusb Driver , this guid should not be there in the registry, as the orig driver has defined some other GUID using DEFINE_GUID macro.

    But when I installed it(the orig driver) this guid was still there.

    How does this GUID{a5dcb…..}  gets installed though I have not specified it anywhere?

    One more doubt,I am using Dsf Simulator to test my driver so when I press enter key in the commandprompt (which removes the device),the device no more appears in the Device manager.How do I uninstall the driver?

    Driver is installed in Target Computer and Debugger is running in Host Computer ,so as soon as the driver loads because of dbgbreakpoint() ,target computer will hang.

    Please suggest some solution. And please explain me at what time of installation  the registry entry for interface guid gets added into the registry.

    Original BulkUsb is working fine,even after all these registry modifications.

    Thankyou for your crucial time.



  148. clay_chang says:

    Hi Doron,

    Yes I implemented a virtual HID keyboard minidriver with 2 top level collections. One is a keyboard TLC, the other is a custom TLC. The custom TLC is used to communicate with the client application. The client application sends data through the custom TLC to tell the keyboard to send keystrokes to the keyboard buffer.

    Everything works fine but I want to implement the C+A+D in the driver. The idea is the client application could send something and the driver should tell the system that C+A+D is pressed.

    How could I implement this? I tried to simply send the scan codes of these three keys, but it didn’t succeed.


  149. doronh says:

    Gaurav, the registry keys persist after the interface was created the first time.  This key is private to the PnP manager so how it is created and managed is not a problem for you.  If you uninstall the device (in device manager for instance), the PnP manager will clean up its own keys.  YOu can uninstall the device before you press enter while it is still enumerated.

    I suggest you start from scratch and no not modify the registry so that you are in a clean state.  As for the hang, attach a kernel debugger and see what is going on.  I can’t tell you more then that without knowing what is hanging.


  150. doronh says:

    Clay, you have to report the keys as usages in the keyboard TLC.  Are you reporting usages or actual scan codes?  The mapping from usage -> scancode happens above your driver (in kbdhid.sys)


  151. sprevost says:

    Hi Doron,

    I’m not sure if you’re dealing with the Device Simulation Framework (DSF), but I’m trying anyway 🙂

    I’ve ported the SoftUSBAudio example (scrtestdsfusb) in managed code (C#) and I’m able to plug/unplug the device correctly. However I’m not able to register to the USBEndPoints event sink . I’m always getting a cast exception, a null pointer or an target invocation binding error (depending on how I try to hook).

    From what I’ve observed it seems that the USBEndPointClass does not implement/inherit the UICOMConnectionContainer and this may be the root of my problem.

    I’m puzzled as the SoftUSBAudio sample is working fine in C++/ATL. It may be (certainly is) a COM Interop issue – but I’m out of ideas, and I do not know if it is coming from my code or the framework.

    I’ve posted a bug/question entry in the WDK/WDF with the source code.

    Any hint/suggestion will be apprieciated.



  152. pshier says:

    DSF does not yet fully support managed code because ISoftUSBEndpoint is not a completely dual interface. We will be supplyng the necessary code to make this work in a coming release. Sorry, but no date yet.


  153. clay_chang says:


    Thanks for the reply. I reported the actual scan code to the TLC. How to report a usage to the TLC in my case?



  154. doronh says:

    Clay, how are you reporting other usages in either TLC?  you need to complete a pended IOCTL_HID_READ_REPORT (which hidclass will send) with the data you want to report.  see the vhidmini sample in either the WDK or server SP1 DDK


  155. gaurav_verma says:

    Hi Doronh,

    I tried running the code on another system.

    Now IoSetDeviceInterfaceState is returning status code = c00000d

    Now what should I do? 🙁

    Is it possible for you to review my code?

    Please,help me.

    After exiting from the DriverUnload routine an exception is raised exception code = 0x7e

    which results in a system crash.

    Is is possible that ,by not following the naming convention for InterfaceGuid,I am getting this error?My Interface GUID name is GUID_BULK_USB.

    Thanks and Regards,


  156. doronh says:

    Guarav, naming conventions do not matter.  The OS does not see the name, it just sees the GUID value.  0xc000000d is STATUS_INVALID_PARAMETER.  IoSetDeviceInterfaceState will return this value in a number of places, most having to do with the string passed in to the API.  Are you sure you are passing a well formed UNICODE_STRING to the API?

    When you get the bugcheck 0x7e (SYSTEM_THREAD_EXCEPTION_NOT_HANDLED), do you have a kernel debugger attached?  If not, attach one.  When you bugcheck, make sure that you have the correct NT symbols and then run !analyze -v.  This should give you a better idea of what your driver is doing wrong.

    I would like to also restate that you should consider moving to KMDF in this driver.  Many of these problems go away and you can deal with the value add you trying to create instead of these types of issues.


  157. gaurav_verma says:

    Hi Doronh,

    Now I am able to enable the interface.Thanks to you.

    I don’t know why ,but the problem was in IoInitializeRemoveLock function in Add Device routine.When I passed the correct argument there,my startdevice function worked.Do you have any explanation for this?


    struct DeviceExtension_tag


         PIO_REMOVE_LOCK RemoveLock;


    corrected :

    struct DeviceExtension_tag


         IO_REMOVE_LOCK  RemoveLock;


    One thing more,I have a doubt regarding usage of IoCompleteRequest().When to use it?I have already gone through DDK documentation.

    Why is it ,that we are using IoCompleteRoutine in IRP_MN_START_DEVICE and not in STOP_DEVICE.

    here both the routines are passing the IRP to the lower level driver(bus).Is it due to passing the same Irp using IoSkipCurrentIrpStackLocation and IoCopyCurrentIrpStackLocation,or something else?

    I tried one thing in IRP_SURPRISE_REMOVE I tried to complete the Irp using IoCompleteRequest.

    so I got 0xe2,because I was using already freed Irp Location.

    Please clarify my doubt.

    Thanks and Regards


  158. doronh says:

    Guarav, is the UNICODE_STRING for symbolic name for the device interface  the next field in DeviceExtension?  If so, you trashed the UNICODE_STRING field by passing a pointer to the pointer of the io remove lock (which really pointed to the next field in your device extension).

    As for IRPs, you should not write another line of code until you have read Walter Oney’s WDM book (2nd edition).  This is a complicated subject and not one that I can answer in a comment…


  159. amit.v.hegde says:


    To test a storport miniport driver, I am trying usig the Device Path Exerciser v 3.2 tool.

    To customize the test I am using the Active Control Test option. However when i use this option with a ASCII text file I get the message

    Invalid Active File Name <fileName>

    where <fileName> is the name of the input file supplied by me

    I am unable to understand the problem. Does this file require any specific name or a file extension.

    I have used a file named dc2verifier.act , but the same problem persists.

    Would appreciate ur help in this matter.

    Thanks & regards

    Amit Hegde

  160. sprevost says:

    (Monday, February 05, 2007 5:58 PM by pshier )

    Hi Peter & Doron,

    thanks for the answer. Knowing that it was a limitation from the framework helped me writing down a work-around. I’m going native (C++/ATL) only to register the event sink of the ISoftUSBEndpointEvents and now all is working perfectly. I’m able to fully simulate any USB device in managed code (C#). This framework rocks !

    Just a remaining strange behavior when I try to handle the generic SET_ADDRESS command (HandleStdRequest = false) –

    1/ the doc example ISoftUSBEndpointEvents::OnSetupTransfer() is incorrect since it reference a non-existing API : put_Address() does not exist for ISoftUSBDevice,

    2/ whatever I do, the full simulation works only if I throw an exception (or return NOT_IMPL) for this particular USB function command.

    Am I missing something ?

    or is it just another consequence of the current static version of the DSF framework ?

    By static, I mean that that I need to know the device configuration in advance, at least the endpoints config, prior attachment, and It seems the framework ignores the endpoints I create on-the-fly (according to device impl).

    I’ve worked around this by implementing a "re-enumeration" that I trigger if I detect a difference with a serialized state of the device  config. Maybe I overlooked something here and it is not supposed to be a pb.



  161. pshier says:

    You are correct about the example in the doc. We will fix that.

    Can you clarify what you are trying to do here? Why do you need to handle SET_ADDRESS?

    Endpoints created after a device has been connected to the bus will be ignored. Why do you need to create endpoints after the device has been connected? At that point the host has already retrieved the device descriptor so how could it know about your new endpoints without re-enumeration?


  162. sprevost says:


    I’ve got a software simulator for my device (a programmable device: .NET smart card). So far our device was not USB capable, but now it is. I want to simulate the USB capability (and also cross-validate our USB impl) using a software-only approach. In order to do so, I was thinking of implementing a lower filter host-controller and link it to my device simulator using IO_DeviceControl() technic, but the DSF came and it looked like a (nearly) perfect match for my need.

    I suspect I’m using the DSF in a way it has not been intended for (like setting HandleStdRequest to false for all the endpoints…), however beside my problem with the SET_ADDRESS command on endpoint 0, it works perfectly.

    Why do you need to handle SET_ADDRESS ?

    As such I do not want to "handle" it in the DSF device, but I want to forward the request to my simulator – I can do that, but when I try to ACK the setup request, the DSF hangs. So far, the only work-around I found has been to throw an exception (or ret NOT_IMPL). I suspect the DSF defaults on an internal implementation that allows the process to resume correctly !? I’d like to know if it is a "pb" coming from me, or from the DSF itself.

    Why do you need to create endpoints after… ?

    I do not want to assume any configuration for my simulated device (since it is a programmable device). So far, to solve that, I’m monitoring the device and configuration descriptor exchange on endpoint0 in the DSF device and if I detect a mismatch with the initial setup the DSF device, I unplug it, re-create an instance of it (using the previously retrieved device and config info) and then re-plug this new updated instance. At this point the DSF device is in sync with my simulator regarding the endpoints and I can hook to all messages possibly sent by the USB Drivers triggered (depending of the number of diff USB interfaces programmed in my device simulator) and forward USB transactions for processing to my device simulator.

    Maybe I’ve selected a wrong approach to an old time issue, and there is a better way to answer my need. If so let me know.

    Rgds and Thks.


  163. jbuxton says:

    Was there every a hotfix issued by Microsoft for USBHUB.SYS for *this* issue ? where you also commented here:

    We are seeing the exact problem reported when we get a SURPRISE_REMOVE event shortly after powering up the device.


  164. RehanAkhter says:


    This is Rehan Akhter from Delhi India.

    I am able to detect the device (like USB, CD/VCD, Ethernet, Modem, Serial Port, Parallel Port etc.) using VC++. bur  want to set security

    (allow read only, allow write only or allow read/write both etc.) to these device. if some code would be available then that will help me alot.

    Thanks in advance

    R e h a n

  165. gaurav_verma says:

    Hi Doronh,

    I read that book by Walter Oney,and hopefully now I have some idea about Iocompletion.Well I have completed my driver and now I am able to read and write data.Heartly thanks to you.

    I want to read about the working of bus drivers and the communication between the device and bus driver,where can I find information regarding it.Any sample bus driver code?

    I want to display what all files are there in the usb pendriver.Like a separate drive in the system. On which, if I click it displays me the files.How to start with it? please give me some initial direction.



  166. doronh says:

    Rehan, there are already tools out there which let you specify the security on a device.  read on what APIs you can use after the device has been installed to set security on the device.

    There is an important problem here though, you are mixing concepts.  USB is a connectivity bus (just like PCI), there is no way to apply an ACL to all USB attached devices.  CD/VCD are media, the CD/DCD drive itself is what is exposed an object which can be ACL’ed.  Ethernet is a whole different problem since applications do not directly access the NIC, they go through several layers.

  167. doronh says:

    Gaurav, if you are asking how to write a bus driver in WDM, Oney’s book is the place to read.  Writing one in WDM is a tremendous amount of time.  You can easily write a minimally functional bus driver in KMDF in a day and fully functional one quickly after that.  KMDF is definitely the way to go if you are writing a new bus driver from scratch.

    The toaster WDK sample has a driver, busenum, which is a bus driver and This sample is avaialable in both KMDF and WDM form.  The KMDF version comes in 2 variations to demonstrate the 2 different models that KMDF presents to bus enumeration.  The busenum sample shows one form of device to bus communication (a private direct call interface provided through IRP_MN_QUERY_INTERFACE).  Typically the communication mechanism between device and bus is IRP based with some form of request block placed in the IRP, just like a USB URB.

    i am not sure what your end goal is.  is it to write a driver that looks like a mass storage device (e.g. a disk) so that you can view files on it?


  168. Joe Dietz says:


    I’m trying to write a tdi port-blocking filter for w2k->vista.  

    Somewhere around XP I can conditionally expect /device/tcp6 /device/udp6 to appear and I would like to be able to attach to these device stacks w/o requiring the user to reboot to get my drivers filtering functionality. Do you have any idea if I can detect the creation of those devices on XP and w2k3 via IoRegisterPlugPlayNotification()?  Initial experiments have not been successful, but I’m not entirely certain I’m using this API correctly yet…  Its also not entirely clear that things like protocol drivers have interface GUIDs, they seem to show up as legacy devices in the registry?

    I’d really like to avoid the obvious alternative of a polling thread or requiring the reboot.


  169. doronh says:

    Joe, IoRegisterPlugPlayNotification wont’ work for you.  IRPPN will only notify you of arrival of PnP device stacks. Devicetcp6 and Deviceudp6 are not PnP stacks.  You either have to poll or have some kind of management interface that directs your driver to attempt to open these devices…

    …but I don’t know if these devices would every show up later after your driver is booted, or at all pre Vista.  Isn’t there an IPv6 release for XP already?  Does it have these devices by these names as well?


  170. Joe Dietz says:

    XP has ipv6, you have to manually install it via ‘ipv6 install’ from a command shell.  Vista obviously has it turned on all the time, which is my dilemma.  Thanks for the info, though I was afraid PnP only was going to be the answer…

  171. doronh says:

    jbuxton, I don’t know if a QFE has been released.  If you need this fixed, I suggest you open an incident with MSFT PSS and request a fix.



  172. akc says:

    How I can allow only read access to a particular USB but not write access on that USB programmatically without manipulating registry settings?

  173. Cristian Berneanu says:

    Hi Doron,

    I want to know why isn’t safe to access locked paged memory at dispatch level through a user-mode virtual address (which is guaranteed to be valid, like the one returned by the MmGetMdlVirtualAddress function)?

    Thank you.

  174. doronh says:

    Cristian, are you accessing the virtual address in an arbitrary context?  or always in the context of the IRP from which you extracted the MDL or buffer?   It is all about context here.  The VA returned is valid at DISPATCH_LEVEL, but only in the context of that specifc process.  If you want to use the VA in any arbitrary context, you must call MmGetSystemAddressForMdlSafe, which will give you a VA that is in sysstem space, which means it is valid in any arbitrary context.


  175. doronh says:

    akc, if you can control the INF in which the device is installed, you can change the access this way.  If the USB device belongs to a particular device class, I am pretty sure you can setup the security on a class wide basis which means all devices in that class inherit those settings.


  176. pshier says:


    If you handle any standard requests you can choose to defer to the default implementation by returning E_NOTIMPL which means "I don’t implement this request". What you are doing with SET_ADDRESS is correct.

    Re pre-configuring the device, I haven’t tried this but I believe you could try not adding any configuration(s) before hot-plugging and handle standard device requests. When you handle the GET_DESCRIPTOR for the config, you can decide at that point how you want to configure the device and populate SoftUSBDevice.Configurations at that time.

  177. Cristian Berneanu says:

    I’m not accessing the virtual address in an arbitrary context, only in the context of the thread that sent the IRP. I asked if it is safe to access the memory through the virtual pointer, when I’m in the right context, on the NT OSR mailing list and they answered that no, it isn’t, but nobody told me why.

  178. talzur says:


    I have encountered the following problem regarding 64 bit and physical addresses using MDLs.

    Lets begin with the fact that I have a PCI board on which there is a number of DSP (PCI devices), the DSP has a DMA capabilities so in order to work on a certain buffer it needs to get the buffer address (physical address). The win32 application would send (using an IOCtl) a pointer to a buffer which was allocated in the user space virtual address (the buffer size is 4K), in the driver I take the pointer and use IoAllocateMdl (…) on it in order to create the Mdl from the buffer, after doing so I call MmProbeAndLockPages(…) in order to lock the buffer in the physical memory, this is done because the DSP in order to be able to access the buffer need it to be in the physical non paged memory. At this point I have noticed a serious problem, the MmProbeAndLockPages(…) can lock the buffer in an address higher then 32 bit, this is a big problem for the DSP because its PCI machine can only process 32 bit address, my question is if there is away to make sure that on a 64 bit machine I would still get physical address in the range of 32 bit ?

    Thanks for your help


  179. ericuday says:

    How to break into a kernel mode driver (no source code available)?


    Hi Doron, I have been trying to learn to use WinDbg to debug a kernel mode driver.

    The situation at hand is: I am trying to analyze a malicious binary file on a WinXP SP2 VMware image using WinDbg as my debugger. All I have is the malicious binary file (Win32 PE executable). I have configured WinDbg for symbol path, also machine is booted in debug mode (after making necessary changes to boot.ini file). The VM machine has no Internet access (since I am dealing with a malicious binary file).

    From using OllyDbg previously I have figured out that the malicious binary file writes a driver file (.sys file) to the windows system directory, then registers this driver as a service via the Service Control Manager (SCM) and then exits. Hence it involves the API calls such as OpenSCManager, CreateService, StartService. After this call there is no use of OllyDbg since it cannot be used to debug kernel mode code. What I wanted to do is step into the driver code that this malicious binary has created and debug that. But I am unable to figure out how this can be done.

    I fire up WinDbg and select File -> Open Executable. Here I select the malicious binary file. Unlike OllyDbg, wherein whenever a PE file is opened for debugging it halts at the entry point of the file. But WinDbg loads the executable and runs it until it hits a breakpoint "int 3" somewhere in the loader. I then stepped out of some kernel code until I was back again in the loaded binary code (application code or disassembly view). Then I placed a breakpoint by issuing the following command ‘bp advapi32!StartService’. Then I issue the ‘g’ command. The breakpoint is hit. I could see that the driver file (xyz.sys) has been created in the Windows System directory.

    Now what do I do? How will I be able to step into the driver code from here, once StartService is executed? I tried setting breakpoint on ‘bp nt!MmLoadSystemImage’ but reports cannot resolve and deffered breakpoint. Well, ntoskrnl.exe module has not been loaded by the malicious binary anyway. I even tried ‘.reload ntoskrnl.exe’ but did not load the symbols for this. Reports module not loaded. I already have the ntoskrnl.pdb cached from my previous download and saved in the symbol path. I also tried ‘bp xyz!DriverEntry’ with again reporting unable to resolve, deferred breakpoint. When I issue the ‘g’ command, program exits and nothing happened. No breakpoint is hit. From IDAPro disassembler I could see that the driver had IoCreateDevice and IoCreateSymbolicLink function calls at the DriverEntry routine. So I issued ‘bp nt!IoCreateDevice’ and ‘bp nt!IoCreateSymbolicLink’ hoping some breakpoint will hit. But again nothing hit.

    Please advice. Thanks in advance.

    PS: I tried to send this e-mail via the question submission page on our blog "A Hole In My Head", but was rejected as spam.

    Eric Kumar

    Anti-Virus Research

    Authentium Inc.

    7121 Fairway Drive

    Palm Beach Gardens

    FL, 33406

    Work Phone: 561-575-3200 x4306

  180. doronh says:

    Eric, are you running WinDbg as a kernel debugger or as a user mode debugger.  For this to work you need to use WinDbg as a kernel debugger (e.g. a 2 machine setup over a serial or 1394 cable).  Once you do this you can set ntoskrnl breakpoints as well as breakpoints in the driver.  you can also use the debugger command, sxe ld <drivername.sys>, to set an automatic breakpoint when the driver image has been loaded but not yet executed.


  181. doronh says:

    Tal, you need to use the built in DMA APIs to build the SG list and use the logical addresses (LA) provided provided to you by the DMA interface.  Rolling your own DMA will not work. Using the DMA interface is the only way to guarantee that you will get a LA that your hardware can decode (there are potentially other issues that could get in way that DMA accounts for).


  182. RehanAkhter says:

    Hi Doronh

    i want to set security (allow read only, allow write only or allow read/write both etc.) to USB without using registry changes and i have to achive using vista

    suppose i have an organisation and there are n number of users and centrally i have to control( who will avail only read permission of USB drive and who will avail Only write permission and who will avail both)

    basically it will protect from data stealing, means nobady will directly copy from their USB and nobady will write something to USB.

    please dear if you got the problem then give me some eyes to it.

    Thanks in advance

    R e h a n

  183. cmartins says:

    Hello Doron,

    I have some questions about the difference between threaded and non-threaded IRPs, and why we cannot allow that a non-threaded IRP be completed by the I/O Manager.

    You say in your post that the field Tail.Overlay.Thread of the IRP is set to NULL for the non-threaded IRPs.

    However, when we analyse the source code for Windows XP (available through Code  Center Premium), we see the following statemente in the function IoBuildAsynchronousFsdRequest:


    irp->Tail.Overlay.Thread = PsGetCurrentThread();


    More, the function IoBuildSynchronousFsdRequest (used to build threaded IRPs) calls IoBuildAsynchronousFsdRequest and then only sets the UserEvent field of the IRP with the event passed as argument, and inserts the IRP in the list of pending IRPs of the thread defined by the field Tail.Overlay.Thread of the IRP, calling IoQueueThreadIrp.

    I do not find anything in the code of IopfCompleteRequest (the implementation of IoCompleteRequest) that distinguishes thread and non-threaded IRPs.

    Apparently, if we let the IRP to be completed by the I/O Manager and the thread that called IoBuildAsynchronousFsdRequest still exists, the IRP should complete normally.

    I don’t undestand why the kernel designers do not make a stronger distinction between threaded an non-threaded IRP in the code of IoBuildAsynchronousFsdRequest and IoCompleteRequest, because if we let a non-threaded IRP complete normally we get a bugcheck with the error code IRQL_NOT_LESS_OR_EQUAL, when the APC is inserted in the APC queue of the thread that created the IRP (in function KeInsertQueueApc), which is confuse. It was more friendly that the code distinguishes clearly the normal completion of a non-threaded IRP and bugckeck with a more suggestive error code.

    If you can tell me whether my analysis is right or wrong, and why this is designed this way, I would appreciate.

    Tanks in advance,

    Carlos Martins

  184. stefanes says:

    Hi Doron,

    I saw som comments on this page regarding the Device Simulation Framework (DSF)…

    I’m modifying the SoftUSBAudio example (scrtestdsfusb) to simulate another device, and that part seems to be working fine.

    The problems come when I try to port the script that plugs in the simulated device, the part that is a VBscript in the SoftUSBAudio example. I just can’t get it to work… what needs to be done to plug in the device using unmanaged C++?

    The test application is a dialog based MFC application, and I "connect" to the COM dll (the simulated device) using #import/CreateInstance(CLSID_…).

    Do you have any sample C++ code that can point me in the right direction? Any hints/suggestions will be appreciated!



  185. Jabeen says:

    Hi Doron!

    i was studying this

    but can you guide me that how can i debug sys files better to be on Local PC or yes at remote LAN PC

    i am newbie although i am able to debug dll and exe files but i am stuck with the sys files. Please guide me how to start for it

    Thanks and Regards,


  186. doronh says:

    Jabeen, you need a 2 machine setup to debug a kernel driver.  The article you are referring to does not run the driver, it just loads it so that you can look at times and the assembly that was generated.  For the 2 machine setup, you must use a serial or 1394 connection.  Debugging over the network is not supported.  If you don’t have 2 machines and your driver does not control real hardware, you can use a virtual machine and debug it locally.


  187. Darin Flippo says:

    Hello sir,

    I want to write a vista sidebar application for my own personal use (at

    least for now) that tells me the temperature for my opteron cpu.  To do

    this, I’ve found that I need to write a kernal mode driver.  Is there

    some skeleton, or hello world type of sample that I could use for

    learning?  In my ignorance, I feel that reading the value from 1

    register should be pretty simple and safe, but the complexity and lack

    of information on writing a kernal mode driver for someone who has never

    done so is near impossible.  I would appreciate any help you could


    Thanks for your time,

    Darin Flippo

  188. sos100 says:

    Hi there,

    I’m from Rococo Software ( For a long time, we’ve

    wanted to build a version of our JSR82 Java/Bluetooth implementation for

    Windows Mobile (and XP, Vista). However, there were no L2CAP APIs

    available, which was a showstopper for us.

    Now – I think there are new APIs in Vista for L2CAP, which is great.

    But what about Windows Moible? Any idea if there are APIs available, or

    due to be available for this, so that we can go ahead and create a new

    version of Impronto for Windows Mobile?

    Any help/direction/thoughts/etc. MUCH appreciated!

    Cheers, Sean

  189. gaurav_verma says:

    Hi doronh,

    I have a question regarding file transfer to a usb flash device.

    If I want to copy some data to an existing file in a usb device,

    who takes care of the location(virtual address) where to write data in the device memory,does function driver need to handle it,or lower level driver read the information about the current file offset from the file object and write data to that location?Can you please give an outline ,what function driver needs to do in this regard?Does function driver simply need to write data to the pipe and pass it on to the lower level driver?And who maintains the device file table?

    Thanks and Regards


  190. doronh says:

    Darin, are you sure that the temp is not exposed via WMI?  Open a command prompt as an administrator (i.e. elevated) and run wmic, and then run TEMPERATURE at the prompt.  Do you get any instances?

    If you really need to write a driver, download the WDK and look at a KMDF sample driver.  You could expose the temperature as WMI which would let you retrieve the temp value in your sidebar gadget using jscript or HTML.  the wmisamp sample shows how to do WMI, but is not illustrative on how to touch I/O ports.  the pcidrv samples demonstrates how to touch ports.  You will need to install your driver on the device instance which is the temperature.  If the BIOS does not describe a device for the temp, then you will need to force a config which assigns you the port…but there will be no way for you to synchronize access to that port with the system components which also read and write to it.


  191. doronh says:

    sos100, I am pretty sure that Windows Mobile exposes L2CAP APIs as well.  Windows Mobile is a speicialization of Windows CE, sop this link,, might help you get started.

    Note that on Vista, the L2CAP APIs are driver APIs, so if you are writing a java abstraction for L2CAP, you would need a driver to translate the user mode requests into kernel requests.


  192. doronh says:

    Guarav, all of these tasks are taken care of for you by the file system (FS) which is mounted on the flash device.  The FS will map file I/O requests to absolute offsets on the disk, your driver should just write/read the bits at the provided offset in the request.


  193. sos100 says:

    Thanks. That answers my question – mostly. I think the key issue for me is this (from that link):

    "Extensions can be written to implement SCO, ACL protocols parallel to L2CAP, and controller management commands."

    In other words – there is no L2CAP support – but you can write your own. Am I correct in this understanding?

    Thanks again for the help,


  194. doronh says:

    Yes, you must write your own L2CAP abstraction before you can expose it in your Java class(es).


  195. Karsten says:

    Hi doronh,

    the first argument of my completion routine does not have a valid pointer to the device object. I build my own IRP using IoBuildAsynchronousFsdRequest, do some stack initializations:


    stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

    stack->Parameters.Others.Argument1 = (PVOID) &urb;

    stack->DeviceObject=DeviceObject; //  has to be set here???

    and then pass the IRP down to a USB driver.

    IoCallDriver(pdx->LowerDeviceObject, Irp);

    NTSTATUS OnBulkTransferComplete(PDEVICE_OBJECT fdo, PIRP Irp, PVOID urb)


        fdo is NULL  ???


    I often see in example code that people using the context of the completion routine to transfer important information, for example, the device extension, but i need the context for the urb.

    Why the fdo is NULL? What I’m doing wrong? Something missing by initializing the stack?



  196. VC_RYK says:

    Hi Doronh

    i want to disable ethernet and internet on a work station through VC++.So can you help me out urgenly.

    some code would be appreciable

    Thansk in advance


  197. doronh says:

    Karsten, this was already covered ;).  read  

    There is another technique you can use other then the extra stack location.  You allocate extra space in your context for your device object.  In this case, it would be

    typedef struct _CONTEXT {

       PDEVICE_OBJECT DeviceObject;

       URB Urb;


    and then you initialize the DeviceObject field with your device object pointer and retrieve it from the context in the completion routine.

    You do not need to do this

      stack->DeviceObject=DeviceObject; //  has to be set here???

    because this is set by IoCallDriver() before it calls into the next driver in the stack.


  198. Karsten says:

    Oh Doronh,

    thx for this both solutions. The extra stack location does make sense for me. But in case of your 2nd technique, how the usb driver underneath me know how to acess the own defined context?  Hopefully it is not a stupid question, but I thought the lower driver (not my) is assuming a pointer to a URB?!


  199. doronh says:

    Karsten, the context to your completion routine and the context URB value to the USB core are 2 different things and can be 2 different pointers.

    CONTEXT context; // assuming the call is synchronous, we can declare the context on the stack, otherwise this must come from ExAllocatePool

    context.DeviceObject = DeviceObject;

    …format context.Urb ….

    IoSetCompletionRoutine(Irp, OnBulkTransferComplete, &context, TRUE, TRUE, TRUE);

    stack = IoGetNextIrpStackLocation(Irp);

    stack->Parameters.Others.Argument1 = (PVOID) &context.Urb;


  200. doronh says:

    VC_RYK, you can use the devcon sample in the WDK as a starting point if you want to use the C level APIs.  it shows you can disable a NIC device. You can also use the Windows Driver Test Framework (WDTF), see for more information.  For instance, you can write a JScript it looks like this:

    var WDTF = new ActiveXObject(“WDTF.WDTF”);
    var Device = WDTF.DeviceDepot.Query(“class=NET AND Enumerator=PCI”).Item(0);
    var DevMan = Device.GetInterface(“DeviceManagement”);

    If you want the NIC enabled but want to disable tcp/ip’s binding to the card, you can use the network configuration interfaces (which i think will let you disable the NIC as well), see


  201. doronh says:

    Carlos (from 2/27), sorry for getting back to you so late.  IopfCompleteRequest requires a valid thread pointer on which to queue an APC.  A non threaded IRP has no thread pointer and the implementation of IopfCompleteRqeuest does not check for a valid (in this case != NULL) thread pointer before attempting to queue the APC.

    Why was it designed this way? I don’t know for sure (I guess I could go ask Darryl Havens who is in the next building and is the orignal I/O manager developer), but I would guess that this was never thought to be a problem.  Furthermore, completing a non threaded IRP back to the i/o manager is an error since the I/O manager only knows where threaded IRPs were allocated from.  Remember that a PIRP could come from a call to IoAllocateIrp or your own memory via IoInitializeIrp.  How would the I/O manager return this error to your driver?  As a return value to IoCompleteRequest?  

    One of the driver factors in the I/O manager was to be as quick as possible with minimal overhead and heavily rely on drivers to do the right thing.  This was a reasonable design decision at the time because everyone who was writing an NT driver was in the same building and could go ask Darryl what to do. This doesn’t scale conceptually, but we are left with the repercussions of those decisions.


  202. Jabeen says:

    Hi Doron,

    By your kind guidence

    I studied many sites and by following…_debug_gsx.html

    I installed WinXP SP2 as target operating system in VM ware and configured the Serial port COM1 on the target system

    now when i run the command from Host system

    C:/WINDBG> windbg -k com: port=\.pipeCOM1,pipe

    WinDBG opens the COM1 port but next to it, it says

    Waiting to reconnect ….

    Later to it there is no response

    how can i debug the driver or sys file?

    Can you kindly guide me through steps.As you know I am new to it

    I will be really really thankful to you.



  203. gsemeraro says:

    Is it possible to have a driver built under the Server 2003 x64 build environment with 3790.1830 DDK signed for 64-bit Vista?  Or does the driver have to have been built specifically for Vista?  What about 32-bit Vista?  I have a client who has bought and paid for such a driver and expects to get Vista for free.  I’m not sure this is the case because the Vista driver signing documentation all refers to the Vista build environment and the 6000 DDK tools for creating a signature.



    P.S. I apologize for mis-posting this in the other blog area earlier this AM…

  204. doronh says:

    Jabeen, I do not use VMware so I cannot help here, but there are many folks who do this type of thing all the time.  Join the OSR NTDEV list and ask there.


  205. doronh says:

    gsemeraro, I am pretty sure that you can get a driver built in a previous DDK to be signed for Vista.  I think the documentation referring to the signing in the WDK has to do with test signing and self signing your binaries.  A driver that was signed for a previous OS (like WinXP or Server2003) will be treated as a signed driver by Vista.


  206. doronh says:

    Cristian (in response to the question asked on 2/20), better late then never.  You cannot access the pointer at dispatch level.  While the page itself is locked (e.g. the PTE), the PDE for the memory is not locked and can still be paged out.


  207. ButA says:

    Hello Doron,

    I’m trying to create a similar driver than the RamDisk driver,

    but the device is a PNP device. Everything worked right until I

    try to unplug the device. Then the debugger breaks on a breakpoint

    in Wdf01000.sys. The WdfLog gives the following information:

    FxFileObject::GetFileObjectFromWdm – Could not locate WDFFILEOBJECT for PFILE_OBJECT 0x86254948

    FxFileObject::GetFileObjectFromWdm – Did a different PFILE_OBJECT get passed to the request than was to IRP_MJ_CREATE?

    This happens even if I set just a couple of callbacks.


    – If I remove SetDeviceType then the breakpoint will not break

    – If I don’t set the create callback then the breakpoint will not break

    – If I use WdfDeviceInitAssignWdmIrpPreprocessCallback for IRP_MJ_CREATE/CLOSE

     requests, everything works but I think it should work with WdfDeviceInitSetFileObjectConfig

     as well…


    P.S. Create and Close callbacks are just stubs…

  208. doronh says:

    ButA, what version of KMDF are you using?  I am guessing a v1.1 or v1.0.  This issue has been fixed in v1.5.  What is happening is that by setting your device type to FILE_DEVICE_DISK, the storage stack (primarily a file system) is loading on your device.  File systems create lite file stream objects (by calling IoCreateStreamFileObjectLis, When these file objects are created, IRP_MJ_CREATE/CLEANUP is not sent down to the disk, although IRP_MJ_CLOSE is sent down.

    FYI, if WdfDeviceInitSetFileObjectConfig  is not called, KMDF will not create a WDFFILEOBJECT for a PFILE_OBJECT, but if it is called, we will create the WDF object.  The dbg breaks you are seeing are because we are seeing a cleanup or close IRP that does not have a matching WDFFFILEOBJECT for the PFILE_OBJECT in the IRP.


  209. talzur says:

    Hi Doron,

    I have a question regarding the way to get device’s Vendor Id and Device ID. In the WDM functions like HalGetBusData(…) were used in order to get devices data. In my driver I need to know the device ID and VendorId of the device because my driver handles two types of devices. This data is needed in the AddDevice function in order to distinguish between the two devices types and act according to the type that caused the AddDevice function to be called. Is there a way to get such information in the AddDevice ?

    Thanks for your help

    Tal Zur

  210. ButA says:

    Hello Doron,

    Thank you for your prompt answer. I’m using KMDF version 1.5.

    I’ve here just a short code snippet to reproduce the break…

    ::KMDF Version::

    Kernel Mode Driver Framework (verifier on) version 01.005.6000


    FxFileObject::GetFileObjectFromWdm – Could not locate WDFFILEOBJECT for PFILE_OBJECT 0x86254948

    FxFileObject::GetFileObjectFromWdm – Did a different PFILE_OBJECT get passed to the request than was to IRP_MJ_CREATE?



     WDF_DRIVER_CONFIG_INIT( &DriverConfig, EvtDeviceAdd );

     WdfDriverCreate( DriverObject, … );


     WDF_FILEOBJECT_CONFIG_INIT( &FileConfig, EvtDeviceFileCreate, EvtFileClose, WDF_NO_EVENT_CALLBACK );

     WdfDeviceInitSetFileObjectConfig( DeviceInit, &FileConfig, &FileAttributes );

     WdfDeviceInitSetDeviceType( DeviceInit, FILE_DEVICE_DISK );

     WdfDeviceInitAssignName( DeviceInit, &DeviceNameUnicode );

     WdfDeviceInitAssignName( DeviceInit, &DeviceNameUnicode );

     WdfDeviceCreate( &DeviceInit, &DeviceAttributes, &Device );

     WdfDeviceCreateSymbolicLink( Device,

    &LinkNameUnicode );


     WdfRequestComplete( Request, STATUS_SUCCESS );



  211. doronh says:

    Tal, there are 2 ways to do this. The first way is to have 2 separate INF install sections.  Each install section writes a value to the registry indicating the type (the 2 sections can share a value name, just the value itself is different).  You then read the value out of the registry during AddDevice and switch on the value.

    The other way is to query the device config, see for documentation on BUS_INTERFACE_STANDARD, specificall the GetBusData function.  Two other references to read are and


  212. doronh says:

    ButA, this should not be happening with KMDF v1.5.  

    Please enable the KMDF verifier on your driver.  Set a bp on both EvtDeviceFileCreate and EvtFileClose.  Also register for EvtFileCleanup and set a bp on it.  Whenever your bp or the framework break hits, capture the calling stack with ‘kb’.  Send me the resluts to me using the email link (it is too large to put into a comment and be readable) in the blog.



  213. Jabeen says:

    Thanks for guidence

    now let me see how they guide coz’ i am still stuck there

  214. talzur says:

    Thanks Doron,

    Querying  the device config seems to be the way,

    I just wonder if there is a more “kmdf” way of getting the device config instead of the IRP_MN_READ_CONFIG.



  215. doronh says:

    Tal, there are a couple more "KMDF" ways to do this, but only after you have created a WDFDEVICE.  After you have created a WDFDEVICE, you could call WdfFdoQueryForInterface to get BUS_INTERFACE_STANDARD or format an IO_STACK_LOCATION and use WdfRequestWdmFormatUsingStackLocation and send the request on the default WDFIOTARGET (WdfDeviceGetIoTarget).  Since you wanted to do this before you created the WDFDEVICE, sending a PIRP manually is the only way.


  216. talzur says:

    Doron, Thanks for the quick response.


  217. anujagarwal3101 says:

    Hi Doron,

    I’m trying to port the WDM version of Parallel Port driver to KMDF.

    In PptDetectChipFilter() function there is a call to build an IRP,

    Irp = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_PARCHIP_CONNECT,






                                           TRUE, &Event, &IoStatus);

    and after that it is passing the IRP down.

    Actually, I’m not finding any replacement for this call in KMDF. Can you please throw some light like which function i should use for that.

    And it would be very helpful, if you can tell me some source from where I can get some help in porting Parallel Port driver to KMDF.



  218. doronh says:

    Anuj, I don’t think anyone has spent the time to convert the parallel port driver to KMDF, so you are on your own.  But the port should not be too hard, it is not that complex of a driver if I remember correctly.  

    In general, IoBuildXxxRequest() calls will be replaced with WdfIoTargetSendXxxSynchronously calls.  To send the IOCTL in KMDF you would do this:

    WDF_MEMORY_DESCRIPTOR inDesc, outDesc;
    status = WdfIoTargetSendInternalIoctlSynchronously(


  219. VC_RYK says:

    Hello Doron

    I have to block write Privilege to floppy drive for a user using VC++ and i am using createfile to block the drive but not able to block writing privilage. so please can you help me is very urgent.

    With regards


  220. doronh says:

    There are a number of tools out there that can set the ACL for the volume, I think will do what you want.  Otherwise, filter on the floppy volume can block all writes (or a file system filter, but i think that might be a bit too heavy weight for what you want).  What file are you opening in your call to CreateFile() ?


  221. VC_RYK says:

    Hi Doron

    Yet i have not got any solution, can i have what what tools are there those i can use, now i am trying to use "SetEntriesInAcl" even this one is not working, Really it quite panic to resolve.

    in createfile i am passing "\.A" as a file. Please dear try to help me out.



  222. wslee says:

    Hi, Doronh.

    I am a beginner in driver development. I am developing a USB device driver for a usb device. Today I encountered a problem in retieving the configuration descriptor of the device. I hope you could help me.

    According to WDK help, WdfUsbTargetDeviceRetrieveConfigDecriptor is available to get the configuration descriptor. But I just wonder how the function works if there are more than one configuration descriptors embeded in the device. Indeed, I want to specified the configuration descriptor index that I want. But I don’t know how to do it.

    Thanks in advance…


  223. doronh says:

    wslee, KMDF only supports the first config descriptor on a device.  Devices with multiple config descriptors do not make much sense to me; for instance, no USB class driver in Windows supports mulitple configurations.


  224. wslee says:

    Thank you for your reply, Mr. doronh.

    In fact, I am writing a no USB class driver.

    So I want to get the specified config descriptor.

    Maybe I should try UsbBuildGetDescriptorRequest.

    OK, thanks once more… ^_^

  225. doronh says:

    wslee, I realize you are not writing a class driver, otherwise you not have to write a driver ;).  I was just pointing out that nearly all of the USB drivers in the OS do not support multiple configurations.

    Why does your device have multiple configurations?  What value/functionality is it adding for your device?  UsbBuildGetDescriptorRequest woudld be the macro you use to get the config descriptor yourself.


  226. regf2603 says:


    I am fairly new at writing drivers, so sorry if this sounds a silly question.

    I have created a class lower filter driver for the USB class.  An user-mode app will send a request down to the driver to block certain devices such as flash drive, mouse, etc… I have implemented an evtIODefault routine that grabs all the IRPs for the USB class.  That works (of course).  But I am now trying to figure out how to associate an IRP with a device.  Someone has tried to tell me about URBs but I am confused where I would get info about these URBs….

    Could you help me?  Or could you point me to some WDF examples that would make me understand this?



  227. Alex Palka says:


    I have been getting a strange KeSetEvent bugcheck. The architecture I am using is the following:

    – a bus driver that manages 2 virtual COM ports

    – a user mode application that communicates with the bus driver

    When the client app is launched, it creates a named evend and sends an IOCTL to the bus driver so that the driver opens the same event (with IoCreateSynchronizationEvent). Just before the client app quits, it sends another IOCTL to the driver to let the driver know that it is about to close the event in user mode (I am not sure if this is necessary…).

    Basically, I need to know in the client app if a VCom managed by the bus has been opened/closed. What I did was to sent IRPs from the VCom ports to the bus driver from their IRP_MJ_CREATE and IRP_MJ_CLOSE handling routines to the bus driver (using internal IOCTL between the drivers). The bus driver sets the forementioned named event in response to those IRPs.

    It works very well most of the time. Sometimes I get a strange bugcheck when the bus driver is trying to set the named event in response to a VCom driver being closed.

    Here’s the corresponding code:


    KdPrint(("Event ptr: 0x%pn", deviceData->ModemEvent));

    if(deviceData->ModemEvent != NULL)

       KeSetEvent(deviceData->ModemEvent, IO_NO_INCREMENT, FALSE);


    The KeSetEvent function is guarded with a fast mutex because I close the event (and nullify the pointer) when the client application is closed.

    Let’s move to the Windbg log:

    Event ptr: 0x821FF1E8

    *** Fatal System Error: 0x0000000a



    Arg1: 00000016, memory referenced

    READ_ADDRESS:  00000016




    804dbda3 6683781601      cmp     word ptr [eax+16h],1



    PROCESS_NAME:  hypertrm.exe

    TRAP_FRAME:  f615b018 — (.trap fffffffff615b018)

    ErrCode = 00000000

    eax=00000000 ebx=821ff1f0 ecx=f615b098 edx=00000000 esi=821ff1e8 edi=00000000

    eip=804dbda3 esp=f615b08c ebp=f615b0a8 iopl=0         nv up ei pl nz na po cy

    cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010203


    804dbda3 6683781601      cmp     word ptr [eax+16h],1     ds:0023:00000016=????

    Resetting default scope

    LAST_CONTROL_TRANSFER:  from 8053225b to 804e3592


    f615abcc 8053225b 00000003 f615af28 00000000 nt!RtlpBreakWithStatusInstruction

    f615ac18 80532d2e 00000003 00000016 804dbda3 nt!KiBugCheckDebugBreak+0x19

    f615aff8 804e187f 0000000a 00000016 00000002 nt!KeBugCheck2+0x574

    f615aff8 804dbda3 0000000a 00000016 00000002 nt!KiTrap0E+0x233

    f615b0a8 804e39f2 82200c70 82200d64 8206fc18 nt!KiWaitTest+0x30

    f615b0bc f88612f4 821ff1e8 00000000 00000000 nt!KeSetEvent+0x58

    f615b0ec f7f5cba4 7ddff388 7df903e0 00000000 baracodabus!Bus_Pdo_EvtIoInternalDeviceControl+0x274 [h:baracodapencilvcombaracodabusbusdynamicbuspdo.c @ 516]

    So the pointer to the user-mode-created event is correct (I check its value right after it is created) but still Windbg believes there’s a null pointer there. Would you have any idea about what is going on?

    The bus driver was based on the toaster KMDF example and the VCom drivers are WDM-based.

    Any help would be appreciated.

    Thanks a lot,

    Alex Palka

  228. angren says:

    Hi, Doronh.

    I am sorry for my English.

    I am writing a KMDF driver for Bt878 chip. I know that device requires AVStream model of driver which not supports now, but I just want learn WDF model. I am using the PCIDRV example. I wrote a simple driver which created device in the EvtDeviceAdd, called WdfFdoQueryForInterface and got a BUS_INTERFACE_STANDARD. Using BUS_INTERFACE_STANDARD.GetBusData I read the PCI Configuration space of my chip. All fields – VendorID, DevID, ProgIf are the same as in the other programs like PCI Explorer which show all PCI devices in the system but one field – Command is wrong(value 0)(3th field after VendorID and DevID). Why other programs show me this field(value 6)?

    Second problem:in the EvtPrapareHardware I enum all given resources – CmResourceTypeInterrupt, CmResourceTypeMemory and output them with DbgPrint. Memory range is the same as I can see in the Property page of device DeviceManager(ex. EE800000 – EE800FFF) but IRQ is different – instead 20 that I see in the DeviceManager I get 194h. Why?


    Why we cant assign to a WDFINTERRUPT object  a interrupt vector number like IoConnectInterrupt?

    Thanks a lot for your time.


  229. doronh says:

    angren, don’t worry about the partical IRQ value.  on a machine with an IOAPIC, the IRQ values exposed to the driver are not the exact IRQ values used in the hardware.  The HAL encodes different values into the IRQ value.  

    As for why you cannot assign a WDFINTERRUPT an interrupt vector, that is because the WDFINTERRUPT uses the resources assigned to the device.  You as a driver, even in WDM, are not allowed to pick arbitrary vectors or values to pass to IoConnectInterrupt, you are supposed to use the values assigned to you by PnP.

    As for issue with the Command field in config space, I don’t know.  Are you sure you are reading at the right offset?


  230. Prabhakant says:


    I have built and installed the KMDF drivers – ‘ndisedge.sys’ and ‘pcidrv.sys’ which I built using DDK 6000. I have an Intel 82557 controller based NIC on my system. That allowed me to load my driver(s).  During my debug session when I have my target and host machines hooked up with Firewire cable, I see the following output when I right click on the NIC and choose properties in Control Panel->Networking window:

    NDISWDM.SYS:WdfIoTargetSendIoctlSynchronously failed 0xc00000bb

    NDISWDM.SYS:NICMakeSynchronousIoctl failed c00000bb

    NDISWDM.SYS:WdfIoTargetSendIoctlSynchronously failed 0xc00000bb

    NDISWDM.SYS:NICMakeSynchronousIoctl failed c00000bb

    NDISWDM.SYS:WdfIoTargetSendIoctlSynchronously failed 0xc00000bb

    NDISWDM.SYS:NICMakeSynchronousIoctl failed c00000bb

    NDISWDM.SYS:WdfIoTargetSendIoctlSynchronously failed 0xc00000bb

    NDISWDM.SYS:NICMakeSynchronousIoctl failed c00000bb

    NDISWDM.SYS:WdfIoTargetSendIoctlSynchronously failed 0xc00000bb

    NDISWDM.SYS:NICMakeSynchronousIoctl failed c00000bb

    At this point, I am not sure how to debug further. I will highly appreciate any suggestions/hints. Thank you.  

  231. doronh says:

    I would guess that you installed your driver on the wrong device node.  c00000bb is STATUS_NOT_SUPPORTED.  Get your device object (!wdfkd.wdfdevice <WDFDEVICE>, get the WDM PDEVICE_OBJECT, or in your case, the value you pass in to WdfDeviceMiniportCreate) and pass that to !devstack <PDEVICE_OBJECT> and look at who enumerated the PDO for your device and if there are filters below your driver which can process the i/o request.


  232. talzur says:

    Hi Doron,

    I’m writing a KMDF driver, I would like to call an IOCTL from a win32. Is it guaranteed that my driver has the context of the

    process that made the request ?. The IOCTL would be handled by my driver with no calls to other low level drivers.

    My purpose is to transfer a pointer (virtual user space) to a data buffer + meta data of the buffer in the IOCTL’s In Buffer, in the kernel

    I would create an MDL from the pointer to data buffer (using ProbeAndLock (…) etc.). If the OS can make a context switch while the IOCTL

    is handled in the driver then the pointer to the data buffer which is virtual user mode address isn’t pointing to the place of the data buffer.

    I thought of using direct IOCTL but this is a problem if I want to send the data buffer with the meta data in the same IOCTL.

    Thanks for your help

    Tal Zur

  233. Prabhakant says:

    Hi Doron,

    Thanks for the previous reply.

    Now, a different question:

    The Windows Driver Kit indicates that the following safe string functions must be executed at IRQL = PASSIVE_LEVEL.    

    While the Device Driver Kit does not mention at what maximum IRQL the above safe string functions can be executed.

      RtlStringCbPrintfW ( …) ;

      Status = RtlStringCbLengthW (…);

    Can the above safe string functions be executed at at IRQL <= DISPATCH_LEVEL?

    Thanks in advance for your help.

  234. doronh says:

    Prabhakant, the answer is it depends on the particular function you are calling and the type of buffer.  The bigger question is why are you manipulating or touching strings at raised IRQL?

  235. doronh says:

    Tal, the I/O manager itself will not swap contexts between a user mode I/O call and the underlying sending of the IRP in the kernel mode driver.  KMDF does not guarantee the caller’s context though when a request is presented in a WDFQUEUE.  To allow you to map buffers, KMDF allows you to specify a EvtIoInCallerContext via WdfDeviceInitSetIoInCallerContextCallback.  The processing is now split.  In EvtIoInCallerContext you map/copy the buffer and then in the WDFQUEUE callback, you process the request/data.  To probe and lock the UM address you would call WdfRequestProbeAndLockUserBufferForRead/Write (note this do not make a copy, just probe/lock).  By using these APIs, KMDF will automatically unlock the buffer upon completion of the request.


  236. Prabhakant says:

    Hi Doron,

    From the DPC we would like to log a message to the system event log. So, we need to construct/manipulate the message string in the DPC. I am not sure what the problem with this approach is. Also, I wonder what alternatives we have here.

    Thanks again.

  237. doronh says:

    You should have a fixed length string that you are putting into the error packet returned by IoAllocateErrorLogEntry().  As such, you really should not need any string manipulation functions, rather it will be a straight RtlCopyMemory into the right offset of the packet.


  238. akc says:

    Hi Doron,

    I have to prevent write operation on USB flash key i.e. no one can alter the contents of USB flash key. This can be done by manipulating registry but our objective is to achieve this without manipulating registry.

    Can we trap windows messages programmatically responsible for writing or updating contents on USB flash key?

    Any suggestion in this regard would be highly appreciated.


  239. doronh says:

    akc, you would need to write a driver for this.  i/o does not flow through windows messages.  Ideally you write a filter on the volume which turns the volume into a read only volume.


  240. talzur says:

    Doron, thanks for the help

    Tal Zur

  241. DclsBOSS says:

    Hello 🙂

    When we call WdfDmaEnablerCreate, we use "devExt->Device" for instance:

    status = WdfDmaEnablerCreate( devExt->Device, &dmaConfig, WDF_NO_OBJECT_ATTRIBUTES, &devExt->DmaEnabler );

    Does "devExt" mean "deviceExtension"?

    And do we have to do something before using "devExt->Device" for instance?

    Thank you!

  242. doronh says:

    DclsBOSS, well, this is your code, so it means whatever you defined it to be.  In a WDM driver, you have a device extension (DeviceObject->DeviceExtension) which you define in the call to IoCreateDevice.  In KMDF, you specify a *context* (vs an extension) on the WDFDEVICE when you create it.  Since most driver writers are used to a device extension, they put their WDFDEVICE context in a local var called "devExt" or "ext" or something like that.  

    > And do we have to do something before using "devExt->Device" for instance?

    You have to create the WDFDEVICE, which you already did, otherwise you would not have a valid devExt pointer or Device to begin with.  Are you encountering some other issue that you cannot solve?  is WdfDmaEnablerCreate failing?


  243. vortical says:

    I have never written a driver before, and I need to write a simple driver for a PCI card.  All I need to do is be able to read the configuration space info and read/write to some registers on the card (offset from BAR 2).  

    I have read through a LOT of the documentation that comes with the WDK install, and a few tutorials that reference the WDK samples.  I have decided that writing a KMDF driver is the easiest/fastest way to get this completed.  

    One of the questions that I am facing at the moment is how to tell the system which piece of hardware I am writing this driver for.  Do I specify the Vendor ID and Device ID somewhere in the driver code, or is it something that is done through a .INF file?  Where do I tell windows that my device is located on the PCI bus?  I haven’t been able to find much on writing .INF files yet… I was kinda hoping that if you couldn’t help me directly, that you could at least point me to some good tutorials/samples/discussions that I can learn some of these basics from.

    Also, do you know how to read/write PCI registers from a KMDF driver?

  244. DclsBOSS says:

    God save Doronh!

    Thank you for the explanation of driver context (WDF) vs driver extension (WDM).

    > Are you encountering some other issue that you cannot solve?  is WdfDmaEnablerCreate failing?

    Actually, I write a code based on the Toaster sample (function driver of course) and I want to add the code for interrupts and DMA.

    I haven’t yet tested my driver…

  245. doronh says:

    vortical, the INF is what ties your driver to your hardware.  Your PCI device will have a hardware ID (one of the IDs is in the format of PCIVEN_vvvv&DEV_dddd, others have subsys or revision in them as well).  The best for you to start is with a sample driver, WinDDK6000srckmdfpcidrvsys is a good place to start.  Look at genpci.inx (which is turned into an INF through some makefile magic).  Accessing registers is also demonstrated in the sample


  246. doronh says:

    DclsBOSS, OK, thanks for the explanation.  To test out DMA you do need to be enumerated by a bus that supports DMA interfaces (like PCI).  You cannot use DMA for a root enumerated device for instance.  As for interrupts, you should use the WDFINTERRUPT object to help you manage the interrupt’s state.


  247. DclsBOSS says:

    doronh, I see that we define the driver context (aka extension) in the header file.

    I see and understand the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro, in order to get the context and use it (devExt->Device for instance).

    But, how is the context filled? Automatically by the framework or "manually" by the driver*?

    * for instance, in the context:

    WDFDMAENABLER       DmaEnabler

    and in the driver:

    status = WdfDmaEnablerCreate( devExt->Device, &dmaConfig, WDF_NO_OBJECT_ATTRIBUTES, &devExt->DmaEnabler );

    Thank you very much!

  248. doronh says:

    WDF_DECLARE_CONTEXT_TYPE_WITH_NAME will declare the context "type" and the necessary infrastructure for KMDF to create a context, but it doesn’t not actually create any context memory. To create a context, you call WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE with an object attributes and specify the context type’s name.    You then pass this object attributes to a Create function (like WdfDeviceCreate).  Upon success, the handle passed back to your driver will have the context associated with it.  Upon creation, the context will be zero’ed out.

    In the example you gave, the DmaEnable will not have a context associated with it since you specified WDF_NOT_OBJECT_ATTRIBUTES in its Create function.


  249. DclsBOSS says:

    "In the example you gave, the DmaEnable will not have a context associated with it since you specified WDF_NOT_OBJECT_ATTRIBUTES in its Create function."

    Ok, but I will find "DmaEnabler" in the device extension, won’t I?

    For instance, in AMCC5933.c:



    fdoAttributes.EvtCleanupCallback = AmccPciContextCleanup;

    fdoAttributes.SynchronizationScope = WdfSynchronizationScopeDevice;

    status = WdfDeviceCreate( &DeviceInit, &fdoAttributes, &device );


    devExt = AmccPciGetDevExt(Device);

    WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig, WdfDmaProfilePacket, devExt->MaximumTransferLength );

    status = WdfDmaEnablerCreate( devExt->Device, &dmaConfig, WDF_NO_OBJECT_ATTRIBUTES, &devExt->DmaEnabler );

    And, in AMCC5933.h:

    typedef struct _AMCC_DEVICE_EXTENSION {

       WDFDEVICE           Device;                

       WDFDMAENABLER  DmaEnabler;         // !!!    

       WDFREQUEST        CurrentRequest;        

       WDFINTERRUPT     WdfInterrupt;

       ULONG               MaximumTransferLength;  

       ULONG               MaximumPhysicalPages;  

       ULONG               Intcsr;                

       PREG5933            Regs;                  

       PUCHAR             PortBase;              

       ULONG               PortCount;              

       BOOLEAN           PortMapped;            



    Do I have all code which shows that I understand the meaning of DmaEnabler in the device context (declaration, filling…)?

    Thank you!

    PS: a little question… Can I configure my interrupts and DMA both in EvtDevicePrepareHardware or must I configure only DMA in EvtDevicePrepareHardware and configure interrupts in AddDevice?


  250. DclsBOSS says:

    I’m sorry to ask you so many questions… But I have two things which interest me:

    _ In the AMCC5953 sample, there is many source files. I saw the description in the WDK Documentation. I study AMCC5933.c  (file for AMCC5933 PCI driver) and AMCC5933.h (prototype file for AMCC5933 PCI driver) but I saw that ISR, DPC and DMA are in Transfer.c!

    If I want to add these functionalities in my driver (based on the Toaster sample), can I code these callback functions in only one source file? (DriverEntry, EvtDeviceAdd… EvtInterruptIsr, etc.)

    _ A general question… Do you have a link that explains the creation of an INF file easily?

    Thanks a lot!!

  251. talzur says:

    Hi Doron,

    I have noticed the following problem with the KMDF:

    I have written a driver which handles two types of devices, each device has its own set of Pnp and power events callbacks.

    While running in debug I have noticed that for all of my devices I call the same EvtDevicePrepareHardware function (the callback function which was registered first).

    I would like to know if several types of devices with several types of Pnp and power callbacks can be handled in the same driver or that the registration to the callbacks for the first device would influence all the later devices.

    Thanks for your help

    Tal Zur

  252. doronh says:

    TAl, pnp callbacks are registered on a WDFDEVICE which means that each WDFDEVICE can have its own set of callbacks.  same with power.  How are you registering the callbacks for each device?  Can you post some code?


  253. talzur says:

    Hi Doron,

    In the EvtDeviceAdd function I check the type of the device which was added to the system. My driver support two types of devices. According to the type of device that was found I call the appropriate XXX_DeviceAdd function. In each of this functions I register the Pnp and Power callback in the same way:


    PnpPowerCallbacks.EvtDevicePrepareHardware  = XXX_YYY_Pnp_EvtDevicePrepareHardware;

    WdfDeviceInitSetPnpPowerEventCallbacks ( DeviceInit,      &PnpPowerCallbacks);

    All this is done before calling the WdfDeviceCreate function.

    It is important to mention that the phenomenon I have notice is has follows:

    I have two types of devices: board and DSP , the OS usually finds the board before it finds the DSP’s (which are mounted on the board), this means that the Pnp and power callbacks of the board are registered before the ones of the DSP. The DSP would register to its own set of callbacks but I notice that the framework calls the boards Pnp and power callbacks even for the DSP (this is quite easy to notice because the number of DSPs is significantly larger than  the number of boards).

    Thanks for your help,

    Tal Zur

  254. doronh says:

    Tal, are you sure that the WDFDEVICE passed to your EvtDevicePrepareHardware is incorrect?  The order in which your devices are added is not necessarily the order in which they are started and in Vista, devices can be started asynchronously so you may be seeing 2 of your devices being started at the same time if you are printing debug logs.  I would suggest that when you get a callback on the wrong WDFDEVICE, break in and run

    !wdfdevice <WDFDEVICE> fff

    !wdfhandle <WDFDEVICE>

    the first will dump all of the registered callbacks, the 2nd should dump the context (i am assuming you are using a different context for each device and !wdfhandle will show you the context type).  Also, run !wdfdevice <WDFDEVICE> fff after you successfully call WdfDeviceCreate to make sure that the callbacks are registered as you think they should be.


  255. talzur says:

    Doron, I’m using windows server 2003, according to the number of times I get into my boards Prepare hardware function I can be sure that there is a problem. In addition I notice that I only enter the boards prepare hardware function with no entry what so ever to the DSP prepare hardware function.  I tried to run the commands in the WinDbg but got  ‘No export wdfhandle found’ and ‘No export wdfdevice found’, does it have any connection to the WinDbg version I’m running (6.6.0007.5) ?

    Thanks for your help,

    Tal Zur

  256. talzur says:

    Doron, I have succeeded to use !wdfdevice <WDFDEVICE> fff and !wdfhandle <WDFDEVICE> , and was surprised to see that my prepare hardware callback wasn’t registered. The situation is quite interesting, in the board device I only register a prepare hardware callback. In the DSP I register EvtDevicePrepareHardware, EvtDeviceD0Entry and EvtDeviceD0Exit. After calling the WdfDeviceCreate for a DSP device if I call !wdfdevice <WDFDEVICE> fff I find out that the registered functions are (and this is the weird  part) the DSP’s  EvtDeviceD0Entry is the DSP’s D0Exit function and the DSP’s EvtDevicePrepareHardware  is the boards prepare hardware function. NO callback is listed for the EvtDeviceD0Exit.

    Here is part of the dump:

    Power policy state history:

    [0] WdfDevStatePwrPolObjectCreated (0x500)

    EvtDeviceD0Entry:  Adif4Mpda!ADIF4_Dsp_Pnp_EvtDeviceD0Exit (f764df80)

    EvtDevicePrepareHardware:  Adif4Mpda!ADIF4_Board_Pnp_EvtDevicePrepareHardware (f764c2a0)

    Thanks for your help,

    Tal Zur

  257. doronh says:

    The lack of a D0Exit in the output could be a sign of soemthing wrong, but could just be a bug in the wdfkd extension.  I think you need to look at your code again and make sure you are not cross pollinating your device init routines.  Internally, there are no cross reference links from one WDFDEVICE to another, so it is not possible for one set of callbacks to accidentally get set from another WDFDEVICE.  It could also be that your functions for the DSP and the board are completely the same and the compiler folded them together.  Turn on the KMDF verifier (not driver verifier) and see if anything is reported.


  258. talzur says:

    Doron, one more important thing that I have noticed using the

    !wdfdevice <WDFDEVICE> fff command and also looking at the WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks is that some of my functions that fill this data structure have the same address this could be a reason for the lack of some of my functions, they could be overruned by other functions. Do you have any idea how this can happend ?


    Tal Zur

  259. doronh says:

    Are the functions which share the same address functionally equivalent?  For instance, WdfDeviceInterfaceReferenceNoOp and WdfDeviceInterfaceReferenceNoOp share the same address on an optimized build b/c they are exactly the same (same parameters, same implementation).  Does this repro on a chk/unoptimized build?  Function folding is only performed on optimized builds.


  260. talzur says:

    Doron, the reason that the function had the same address was that the functions were at this point empty, after adding content to them the address problem was solved. The only problem that I still encounter is that the EvtDeviceD0Exit can’t be registed. I notice that the EvtDeviceD0Exit function is added to the WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks  but after the device create while using the !wdfdevice <WDFDEVICE> fff  I see that the event wasn’t registered.


    Tal Zur

  261. talzur says:

    Doron, the problem was started because of empty functions that were considered as one by the optimizer. After adding the content to the function (which was different of course) the problem has finished.


    Tal Zur

  262. nkobik says:

    Hi Doron,

    I have two questions.

    The first regarding device symbolic name and the second regrarding device PCI info.

    1. in my driver i assign a symbolic name to a device using the WdfDeviceCreateSymbolicLink  method from the AddDevice routine.     my question is if and how can i access/retrieve this name from other areas of my driver (kernel).  the reason i want to access this name is that somewhere in the process i pass some symbolic names to win32 so an application would use the CreateFile method with the symbolic names previously created by me to access the device.   i try to deal with using interfaces but i can’t find any method to retrieve this name.   when i use IogetDeviceInterfaces i get a system crash.

    2. for each device that my driver handles i need to extract the device’s bus number and Device number(i.e slot number on the bus).  i can successfuly access the bus number using the WdfDeviceAllocAndQueryProperty method and the DevicePropertyBusNumber property flag.  i can’t seem to find any flag that enables extracting the "slot" number. i can only get a string representing the PCI info using the DevicePropertyLocationInformation flag  but as i said, i get a string back which i need to parse.  is there a way of retrieving the "slot" number as a number ?

    thanks a lot,


  263. Ted Lin says:

    Hi! Doron,

    I write a software driver by WDF.

    I want it get the ICH7’s smbus interrupt.

    Is it possible?

    I find a driver on my system. (Device Management)

    It is "Intel(R) 82801G(ICH7 Family) SMBus Controller-27DA".

    In the driver’s detail, The Property "inf Section" is NO_DRV.

    The driver resource is IRQ4, (SMBus Interrupt setting)

    Could I write a software driver or filter driver to get the interrupt in? (SMBus Interrupt)

    If yes, where can I find the relate document?

    I research a long time, but I do not get any solution about it.


  264. VC_RYK says:

    Hi Doronh

    i want to detect at run time what kind of device is connected to USB port(like if Digital camera is connected then it shows Digital camera etc.)like how our windows is showing(if you cannect scanner to USB port then in My computer you can see in "Type" Image scanner.

    i using "setupDiGetDeviceInterfaceDetail" can i have some idea.

    Thanks in advance


  265. doronh says:

    Kobi, what is the callstack and bugcheck parameters when IoGetDeviceInterfaces crashes?  Device interfaces are the correct way to do this.  By using device interfaces you do not need to pass any names to your application, the appliaction can enumerate the names on its own (and be dynamically notified when they arrive after initial enumeration).  As for the slot number, i don’t think there is a way to retrieve this as a number…but why do you want to get this value?  It is very common for the software reported slot number to *not* match the number on the hardware itself.


  266. doronh says:

    Ted Lin, the only way you can get access to the SMBus interrupt is if you are in the PnP device stack for the root of the SMBus.  It seems there is such a device, the "Intel(R) 82801G(ICH7 Family) SMBus Controller-27DA".  What you need to do is install your driver on this device (and not as a filter since you will be the function driver).  Once you install your driver on the correct device, you will get the interrupt information in EvtPrepareHardware in the translated resource list (WDFCMRESLIST)


  267. doronh says:

    VC_RYK, do you want to know about specific types of devices or all USB devices plugged into the usb controller?  For specific types of devices, you must register for notifications on the appropriate device interface.  If you want to be notified of any usb device that is plugged in, that is not really possible.  why do you need to know about every usb device plugged into the machine?


  268. VC_RYK says:

    i am able to notify the devices which are being pluged in on USB port but not able to recongnise which device it is. Like Digital camera, sanner etc. Thing is , How windows is recongnising these device.

  269. doronh says:

    Windows does not recognize the device itself.  What happens is that the device that is plugged in has a driver loaded for it.  That driver then exposes one or more device interfaces.  Specific parts of windows know how to listen for specific device interface events.  This is how the scanner UI knows a new scanner shows up.  it does not listen on usb events, it listens on device interface events.  Given a random device that is plugged in, you can’t know what it does until the driver that controls it loads and exposes the correct functionality.


  270. VC_RYK says:

    "Specific parts of windows know how to listen for specific device interface events "

    Can i do this in my own application too? i.e. my application must be able to know which type of device is being plugged in to the usb. How should i go about it? How can i register with the various device drivers such that i get a notification whenever a device is plugged in.

  271. doronh says:

    VC_RYK, on XP and later you can call RegisterDeviceNotification with DEVICE_NOTIFY_ALL_INTERFACE_CLASSES, this will tell you about all interface changes on all busses, see  you will have to know about each device interface GUID to know what the functionality it represents, there is no way to find a generic functional mapping at runtime.


  272. nkobik says:

    Hi Doron,

    thank you very much for the answer.

    about the callstack and bugcheck parameters i will do some checking and get back to you.

    also, will it be correct to understand from your answer that, in general, passing a string (strings) from kernel to win32 is not

    a desirable operation ?    should i prevent myself from doing so ?

    if not, can you please describe which string type is the best to use (a type known to both win32 and kernel) ?

    again, thanks a lot.


  273. doronh says:

    you can pass null terminated strings just fine, it is just a little hard to get it right and validation the buffers.  But, my point is not that passing strings back and forth is hard, my point is that you are reinventing existing functionality.  Device interfaces do everything you are trying to do and they do it in a better way.


  274. Ted Lin says:

    Hi! Doron,

    I write a driver to control an I2C device via the ICH7’s smbus.

    I am just polling the register to check the SMBUS ready or not. (My driver work well.)

    In the smbus control, I can set a interrupt for the smbus data ready. So I try to do that.

    The "Intel(R) 82801G(ICH7 Family) SMBus Controller-27DA" is installed when I install the Intel ICH7 driver.

    In this situation, could I write a driver to replace the above driver?

    Or is there any method to co-work with the "Intel(R) 82801G(ICH7 Family) SMBus Controller-27DA", like a filter druver?


  275. himanshup says:

    hi doronh,

    first of all thanks !

    I developed ndis im driver with windows ddk for packet filtering. But when  i am trying to build thisdriver or even sample passthru driver with WDK (2003 SP1) it just gives one warning which is written in makefile. and gives up without compiling a single file. If i change makefile with previous single line makefile. i only get 73 errors !!!

    Please help me


  276. lousky says:

    Hi Doron,

    I’m designing a driver that should work with a DMA device. The device is TI DSP. My requirement from the hardware engineers is that they will support hardware scattergather. I don’t want the system to use map registers since my solution needs to support hundreds of DMA transactions.

    The HW engineers ask two questions that I find it hard to give a straight answer:

    1. What is the maximum number of fragments that a 4K byte buffer can split into? The buffer was allocated via the user mode, and was part of a larger buffer (for example 1000 buffers of 4K in one malloc call).

    2. In case of fragmentation, what is the minimum size of a fragment? HW guys say that the DSP support minimum DMA transaction of 32 bits.

    I appreciate your help.


  277. DclsBOSS says:


    1. Maybe, you can check the WDK:

    a) WdfDmaEnablerSetMaximumScatterGatherElements

    "If your driver does not call WdfDmaEnablerSetMaximumScatterGatherElements, the framework uses a default value of WDF_DMA_ENABLER_UNLIMITED_FRAGMENTS, which means that there is no limit to the number of scatter/gather elements."

    b) WdfDmaEnablerGetMaximumScatterGatherElements

    "The WdfDmaEnablerGetMaximumScatterGatherElements method returns the maximum number of scatter/gather elements that the device and driver support, for a specified DMA enabler object."

    2. I only know WdfDmaTransactionSetMaximumLength

  278. VC_RYK says:

    Hi Doronh

    i want to get Unique Id of a particular device connected through USB FIRWIRE Port.

    IS Serial number unique? so how will i find find it of a device (like digital camera,scanner etc.)

    i am able to get serial number of storage device(like USB flash Key, eternal Hard disk).

    With Re

  279. doronh says:

    Ted, you could write a driver to replate the Intel driver but I don’t know what side affects would result from such an action.  I don’t know what loss of functionality you will have.  You will have to contact Intel to see if their driver exposes a way to work with the resources that it owns.


  280. doronh says:

    himanshup , I don’t have enough context in which to answer you question.  If you are taking a sample from the Vista WDK and trying to build it on the Server 2003 SP1 DDK, that will probably not work.


  281. doronh says:


    #1 – 2 fragments

    #2 – whatever the buffer alignment requirement is dictates the minimum size.  If you make your alignment requirement 4-bytes then you’ll be fine.  Without an alignment requirement set on the device the driver could easily find itself with a 1 byte fragment.  You can set the alignment on the device by calling WdfDeviceSetAlignmentRequirement (

    (thanks to peterwie for providing the answer)


  282. doronh says:

    DclsBOSS, i am not sure what your question(s) is.  are you saying that the docs are referring to DDIs which do not exist?  WdfDmaEnablerSetMaximumScatterGatherElements and WdfDmaEnablerGetMaximumScatterGatherElements are both documented and exported.


  283. doronh says:

    VC_RYK, it depends on how unique you want it and where the serial number comes from.  A usb device can have a serial number which should make it unique on the usb bus.  if the device is also connected over 1394, it won’t have the same serial number at the connection layer.  On the other hand, if you are getting a hard drive’s serial number, it should be the same regardless of how it is connected to the PC.    

    For other types of devices like scanners or cameras, if they don’t have a USB serial number there is no way to get a unique ID for the device.  this is the same problem the OS has when you move a device from port to port. If the OS can acquire a bus unique ID, the device will not be reinstalled when plugging into a different port, but if there is no unique ID, you get a found new hardware popup and reinstallation.


  284. doronh says:

    VC_RYK, it depends on how unique you want it and where the serial number comes from.  A usb device can have a serial number which should make it unique on the usb bus.  if the device is also connected over 1394, it won’t have the same serial number at the connection layer.  On the other hand, if you are getting a hard drive’s serial number, it should be the same regardless of how it is connected to the PC.    

    For other types of devices like scanners or cameras, if they don’t have a USB serial number there is no way to get a unique ID for the device.  this is the same problem the OS has when you move a device from port to port. If the OS can acquire a bus unique ID, the device will not be reinstalled when plugging into a different port, but if there is no unique ID, you get a found new hardware popup and reinstallation.


  285. lousky says:

    Thank you for your answer.

    Regarding the answer for the first question (number of fragments = 2) – does it based on map registers or actual fragmentation on the physical memory?



  286. DclsBOSS says:


    I tried to answer to lousky, sorry!

  287. ykwang says:

    Dear  doron:

         I am writing the PCI bus storage WDM driver, and encountered a problem these days only in Vista. (the problem will not occur on XPSP2).  And the operation is "copying files to the storage device  (like MS/SD) , before finished, to enter power saving (sleep/Hibernet) mode, sometimes window will show error message as follow. error 0x800703EE: The volume for a file has been externally altered so that the opened file is no longer valid"

         Before power saving, what should we do first to avoid to copy file error(I think only one file will be error) ?  

           This is my first time to ask question . I have no idea if it’s decency. Thank you anyway.


  288. Kamala says:

    Hi Doron,

    I am having trouble using IoRaiseInformationalHardError in Vista.  I stepped into the API implementation and was able to determine that a work item was queued successfully and IopHardErrorThread was invoked as expected and it was writing to the ALPC port.  However, I didn’t debug the listener port to determine whether it received the message and if so what it did with the message.  I am starting to wonder if some vista security/configuration (possibly csrss process related) is blocking the message from getting displayed and thought I would check with you before I spend more time debugging this.  As always, thanks for you time!

    – Kamala

  289. Ted Lin says:

    Hi Doron,

    I have contacted with Intel.

    They just tell me as below.

          We don’t provide any method for ODM to implement their own drivers.  If you would like to develop a standalone driver, you may be on your own risk.

    I have a question abiut the smbus interrupt.

    The interrupt is an inside interrupt of smbus controller. it is not design to a hardware pin or any register.

    How do I set the EvtPrepareHardware?

    I use create Interrupt object to my driver.

    But it seems to no wrok.


  290. adatia says:

    Will the driver built for XP32 work on Vista32?

    I have developed a driver for a PCI board which requires only memory & interrupt resources. I am using WDK6000 and KMDF1.5 to build the driver. I have following questions:

    1) Will the driver built for XP32 work on Vista32?

    2) Are the libraries used during build for XP32 and Vista32 different?

  291. DclsBOSS says:

    1) Yes, try with a WDK sample 😉

  292. adatia says:

    Hi Doron,

    I have a WDM version of a driver for a PCI board.

    I have ported it to KMDF and built it with KMDF1.5.

    The original WDM driver loads fine on Vista32 and the application also runs well even with UAC enabled or as a non-administrator user.

    But with the new KMDF version driver, I get following issue: When UAC is enabled or I run as non-administrator user, the application gets ‘Access Denied’ error for CreateFile call.

    What could be the issue?

  293. doronh says:

    adatia, please for why only an admin can open the device.  you have to explicitly enable users other than administrators to use a device object which you named.  This brings up the question of why did you give the device a name in the first place?  Just use a device interface and you don’t have any of these issues.

    as for the other questions. 

    1) yes, a driver built for XP 32 bit will load on Vista 32 bit.  Will it work without changes?  Most likely yes, but there is no guarantee.  The OS and the components you interact with might have changed so there may be runtime issues for you to fix.   This is true for any new Windows release.

    2) which libraries?  most of the libraries you are using are import libraries which just resolve the functions that you use into exports from ntoskrl.exe or hal.dll.  these libraries have no code in them.  other libraries like ntstrsafe.lib do have code in them and they have changed from the XP DDK to the Vista DDK version.  Typically (but not always) you will use the same libraries for an XP or Vista build window, other factors will control what gets exposed/linked into your driver.


  294. doronh says:

    Ted, WDFINTERRUPT only works if there is a hardware interrupt assigned to your device in the CM_RESOURCE_LIST created by pnp.  if the interrupt is not exposed to the OS and kept internal to the hardware, there is nothing you can do in a driver to get at it.


  295. doronh says:

    Kamala, i would guess that there are issues on Vista with IoRaiseInformationHardError due to all services running in session 0 and not having any logged on user running in that session (vs previous releases where the first logged on user would run in session 0 as well).  Then again, this could be by design and explicitly broken.  I don’t know the definitive answer.


  296. DclsBOSS says:

    Hi Doron,

    Can we use SDV and PREfast for a WDM driver…?

  297. doronh says:

    Yes, SDV and Prefast for drivers (PFD) can be used on a WDM driver.  PFD can also be used on a KMDF driver, while SDV in the 6000 WDK is limited to *only* WDM drivers.  The next version of SDV in the next WDK will support KMDF as well.


  298. tinylaser says:

    I have a general question regarding USB drivers that seems to not be covered anywhere that I can find.  

       My question is regarding when two or more of our devices are plugged in.  A typical scenario is that one instance of our user software will have an open handle to the interface of device0 (call this processA).  ProcessB will be the second instance of our software that has an open handle to the interface of device 1.  If ProcessB is communicating away and Device0 gets unplugged, Device1 inadvertently becomes Device0 and ProcessB has to reopen the handles to Device1 as if it was Device0.  The driver writer tells me this is normal behavior for USB for the instances that are kept track in the USB stack to "move around".  

     This sounds fundamentally wrong to me but I can’t say that it is seeing as how I know little about the Windows USB core.  Can anyone help me answer this question?

    Thank you for your time,

    Jeff Warren

  299. doronh says:

    jeff, this is expected behavior. if your device does not have a serial number, the usb core does not know that it is the same unique device moving from port to port.  If it has a serial number, the device is installed once and remains the same device instance no matter which usb port it is plugged into.  if you need your device to maintain identity wherever it is plugged in, report a serial number for the device.

    But why would the application have to reopen a handle to the 2nd device if the first is unplugged? Are the 2 devices interconnected/related?  


  300. tinylaser says:

    The two devices do have unique serial numbers that follow the USB spec for serial numbers (e.g. "247070001").  The serial numbers are accurately shown by Windows under the enum USB key for our VID/PID pair.  This is what is so confusing!?  

       As far as the question of reopening the handle, I agree with you entirely the application should not have to reopen a handle when the other device it is NOT communicating with is removed.  Yet this is not the case.  The handle that is opened is to an interface and when two devices are plugged in and one is unplugged, the application with the open handle to the device that remains plugged in gets "moved".

     What I am told by our driver writer is that if instance 0 is removed and instance 1 is still active, the driver framework moves the resources from instance 1 to instance 0, which changes the symbolic links and therefore the handles that the application has open are no longer valid.  

     This seems fundamentally wrong to me, but I have been told this is how the USB framework works.  If I understand you, you are agreeing with what I am saying that there is something wrong with our driver.


    Jeff Warren

  301. Ted Lin says:

    Hi! Doron,

    I try to find the interrupt of SmBus Controller.

    I boot in DOS mode.

    Then, I use the debug to modify the interrupt 6 to jump memry to 6000:0000.

    I write a simple code to clear screan in the memory.

    I set the smbus interrupt to 6.

    I call the SmBus command with the interrupt control.

    Then the screan is cleared.

    So I think this interrupt can work well.

    Sorry, I give you a wrong answer.

    I use the command "devcon install MySensor.inf PCIVEN_8086&DEV_27DA" to install the driver.

    Is it right?

    If I want to write MyDriver, I refer the sample of the folder WinDDK5384srckmdfpcidrv, does it suit me?


  302. Josh_A says:

    Hi Doronh,

    What has to be done with the PNP IRPs that a driver receives when the driver is in a PNP state at which it cannot accept the IRP?

    For example, Will START_DEVICE irp be issued when the device is at Stop pending or remove pending state?

    Can you provide a list of states for each IRP, at which the IRP can be occur?



  303. doronh says:

    josh, the table of transitions is quite large.  in the particular case you asking about, when you are in a query remove state, the only 2 pnp irps you can recieve are remove device or query remove canceled.  same applies for the query stop state, you either receive a stop device or a query stop canceled.


  304. Josh_A says:

    Hi Doronh,

    I hope, when in query stop state, a surprise remove irp can be received as well.

    It is not well documented on which IRPs can be received in which state. The state diagram in the DDK documentation under "State Transitions for PnP Devices" does not cover all states / state changes.



  305. doronh says:

    in query stop/remote, you will only get a cancel query/stop or a stop/remove irp.  if you fail the stop irp itself, you can get a surprise remove irp from that state, so i guess if an upper driver fails a stop irp (which it is not allowed to do, that is breaking the rules) i guess you could get a surprise remove in the query stop state.


  306. Ted Lin says:

    Hi! Doronh,

    I modify my software driver.

    I add pnpPowerCallbacks in my DeviceAdd.

    Then register it by WdfDeviceInitSetPnpPowerEventCallbacks().

    I add WDF_INTERRUPT_CONFIG_INIT in the same function.

    And I create interrupt object by WdfInterruptCreate().

    In my PrepareHardware function.

    I use the WdfCmResourceListGetCount() to get list count.

    And use the WdfCmResourceListGetDescriptor() to get the


    Then I use "Devcon update mydriver.inf PCIVEN_8086&DEV_27DA" to replace the Intel’s SmBus controller in the device management.

    It works, I have replace it, but the IRQ is changed from 4 to 17.

    Do the IRQ change is normal?

    I just show infomation in the PrepareHardware function.

    I found the WdfCmResourceListGetCount is 3.

    They are CmResourceTypePort, CmResourceTypeDevicePrivate and CmResourceTypeInterrupt.

    I am a new hand on this topic.

    Is it enough to receive the interrupt?

    Or I must to add some more to resupply about the interrupt?

    Thanks for your help.

  307. Ted Lin says:

    Hi! Doronh,

    I have a question about InterruptIsr and InterruptDpc.

    I find a entry into my InterruptIsr function, then I call the WdfInterruptQueueDpcForIsr(interrupt) function to send DPC.

    Then the InterruptDpc function works.

    Do I need to clear Interrupt?

    Or the sysytem will clear the interrupt automatically by my return is true?


  308. doronh says:

    Ted, in your EvtInterruptEnable you will need to enable the hw to generate interrupts.  You will probably also need to register an EvtDeviceD0EntryPostInterruptsEnabled to do some passive level initialization of the hw.  The IRQ changing should be fine and not an issue.

    As for clearing the interrupt, yes you need to disable the interrupt in the ISR and then enable it again in the DPC once have read all of the relevant state from the hw.  Returning TRUE from the ISR tells the OS that you handled the interrupt and to stop calling other ISRs connected to the IRQ.  Think about your question though, how would the OS know to turn off the interrupt by itself?  Every piece of hardware has a different way of doing this and the OS does not have specific knowledge of any device (this is changing though, with PCI 3.0 there are standardized registers which the OS can use to change interrupt state on its own).


  309. Ted Lin says:

    Hi! Doronh,

    It works. ^_^

    In the interruptISR function, I must clear smbus interrupt first.

    Then I return true, and read data and clear the register in interruptDpc function.

    I won’t do twice read by one interrupt again.


  310. says:

    Hi Doronh,

    I am writing a KMDF driver ( Bus driver for pcie). The requirement is unique , the new device behaves as an End point, so the BISO/OS enumerates it as a normal device. But infact it is a bridge. So my driver will be loaded and my driver will enumerate all the devices attached to this bridge. The Pnp has assigned the H/W resoures (io/Mem). Now my job is to distribute this resources to the child devices. The problem is when I assign the resources to child devices , Pnp manager says, conflict of resources between parent and child device to which I have allocated. So How do I tell OS that I My driver(parent driver) will not use the resources but the resources will be passed down to the child devices. And also I observed that in Device manager PCI bus driver shows the resources which are used by the devices enumerated by it and those devices are also using that resources. Please help me out in this matter. I want see the the same resources shown in Device Manger for both my Bus driver and also child device.

                                                 Thank You.

  311. doronh says:

    Ted, great to hear!  Glad you got it working.


  312. doronh says:

    Kiran, what you are trying to do (reassign resources assigned to your parent to your children) is called resource arbitration.  Unfortunately, the interfaces to implement resource arbitration in a bus driver are not documented.  This means that you cannot do this yourself in your driver.  You have 2 choices to fix this.

    Your first choice is to correctly report your device as a bridge instead of an endpoint.  If you do this, the OS will load the correct drivers with no INFs written by yourself and then things should work as expected.

    Your second choice is to use mf.sys to arbitrate the resources.  MF.sys is an inbox driver which can be "scripted" to split up resources from a parent device to its children devices.  For this to work properly you need to write an INF and tell MF.sys what to do.  This is documented here,

    I would guess that option one is not a choice for you, so i suggest you try to use mf.sys to accomplish your goal.


  313. Ted Lin says:

    Dear Doronh,

    I have a question abou the delay in wdf driver.

    I use the WdfInterruptQueueDpcForIsr(Interrupt).

    Then I read data in the InterruptDpc function.

    But I must read I/O port to poll the status before the data is ready. (I always need to polling about total 1500 times, i use the block read in I2C mode.)

    Could I use something function to delay 50 microseconds in the DPC?

    And Coudl it will take effort on the system?

    I find a function KeStallExecutionProcessor() in WDM.

    Is there the same function in WDF?


  314. doronh says:

    Ted, WDF does not wrap all of the OS so there is not a one to one relationship between WDF and OS functionality.  In this case, you can and should call KeStallExecutionProcessor to delay for 50 us.  How many times are you going to call it? Your DPC should also be very short. If you are going to have any kind of delay i would suggest that you queue a work item and spin at passive level.


  315. says:

    Dear Doronh,

        Thanks for replying. But my problem still persists. The problem is the device is Not exactly a bridge. It is a PCI-Express complient ROOT COMPLEX (RC). So I cannot use the mf.sys since it is not a Multifunction device. The board is still under development and requirement is to validate the functionality of RC. So the RC behaves during boot time as END POINT and it gets IO and Mem resources. After that, through my bus driver I have to pass the resources to child devices attached to RC. I will be very glad if you provice some information on ARBITER_INTERFACE and its usage.

                                                      Thank You.

                                                                                     Kiran S

  316. ComPort says:


    I’m trying to debug an issue where an IRP passed to my TDI filter driver’s InternalDeviceControl dispatch routine has a CurrentLocation of 0. This seems to indicate that the IRP has run out of stack locations (running on Windows 2000 vmware testbed). In fact, I do get a BSOD with the IRP_NO_MORE_STACK_LOCATIONS  (0x35) bugcheck.

    Am I right in assuming that CurrentLocation == 0 should never happen for my filter driver ? Would appreciate some insight on this – have done a little hunting (Oney etc) but nobody specifically talks about the way the CurrentLocation numbers are assigned (i.e. 0 = top of stack or bottom, or below bottom?)

    As far as I understand, this is happening because Win2K’s SMB code doesnt allocate enough stack locations, and so as a driver at a lower level, my filter driver gets an IRP with insufficiently many stack locations. I do have ideas on solving this, just need to understand what CurrentLocation indicates.

    Any insight would be appreciated 🙂

  317. nkobik says:


    i want to present a problem im trying to solve and then the solution im trying to implement, until now without success and i would love to hear if you see anything that i’m missing here.

    the requiremnets im facing are – allocate IObuffers in the kernel, each has a fixed size of 4k.  these allocations must be alligned to

    seperate pages because my hardware currently does not support DMA or scatter-gather so in order to work properly all the data of a buffer must reside in a single memory page which must not be paged out.

    until today , this was done by allocating cached aligned pages from the nonPaged pool.  today this won’t be good since i will need more memory the the NonPaged pool has to offer.

    so, my solution for now will be to allocate these buffers from the paged pool using ExallocatePoolWithTag ,  then allocate MDL for each buffer and lock the buffer – MmProbeAndLock.  i save all the MDLs (mdl per allocated memory buffer)  in a list so i can free them

    when needed.  until now i get system crashes. although it seems that the allocation passed  the system crashes due to some page fault which is not a part of my flow.

    would be great to hear your opinion.



  318. ComPort says:

    Update: I seem to have resolved my issue using the most inelegant solution – just skipping this IRP stack location for such IRPs. In any case, my driver doesnt need to handle SMB/similar – the higher level drivers that actually end up messing this up.

    I also attempted to create a new IRP with adequately many stack locations, setup a special completion routine for it where I free it and complete the corresponding under-stacked IRP.

    However, for some reason this seemed to result in memory corruption [Paged Pool] – and in any case, this doesnt seem to offer any advantages over the above quickfix for my specific case.

    Would still love to hear your thoughts on this issue. Thanks for listening.

  319. torque says:

    Dear Doron,

    Thanks for doing such great work on KMDF, doing interviews and keeping your blog alive.  I have a question for you.  I would like to leverage KMDF to build a device driver which turns RAM into a FAT or NTFS ramdisk.  Can I use KMDF to do this?

    Here are the catches:

    1. I need to allocate 100+ GB of RAM for this

    2. I need to physically place data into a known memory module in a known stick of RAM

    I have an 8 processor x64 box with 128GB RAM running Windows Server 2003 Enterprise 64-bit.  Presumably each CPU will have to keep control of some amount of memory.

    I can do it in Linux… Can you advise or point me in the right direction (books/people/etc.)?  Thanks again for your time.



  320. JohnnyLuo says:

    Dear Doron,

       I have a HID device(a kind of scale device) which have 8 Configurations,When I plug it to my computer, the OS can recorgnize it as a HID device, and by default it will select the first configuration.  

      My question: How can i change the configurations?

      Do I need to write a HID Minidriver? or a filter driver? Can I use the KMDF to implement the driver?

    Thanks and regards

    Johnny Luo

  321. P N Rajesh says:

    Hi Doron,

    I need an extra stack location for an IRP that I allocate,

    #1. pIrp = IoAllocateIrp( Lower Device Object’s Stack Size + 1 );

    #2. stack = IoGetCurrentIrpStackLocation( pIrp );

    FDO —> Stack Location[0] for FDO




    PDO –> Stack Location[1] for PDO

    Is the value returned in Step #2, the address of Stack Location[0], or Does IoGetCurrentIrpStackLocation return address of Stack Location [-1] ,which does not exist?

    Why should I use IoSetNextIrpStackLocation?



  322. gaurav_verma says:

    Hi Doronh,

    I need to remap a Serial COM1 port to any other unused port number. Kindly give me direction to program it. I donot want to use GUI ->port settings.

  323. Otavio says:

    Hi Dorohn, good morning,

    i’m developing a simple parallel interface to communicate with a development board using the parallel port. For doing this i will need a full raw access to parallel port. I’m working on a device driver to do this and would like to know if you could give me a little tip on which way i should take.

    I’m thinking on developing a FDO driver over the system parallel drivers to acquire the parallel port control. I’m worried about IEEE 1284 standard. My hardware is very simple and will use only the data pins to comunicate with PC. Can i do it as a raw device, ignoring the IEEE 1284?


    Otavio Ribeiro

  324. strik says:

    Hallo Otavio,

    you might want to have a look into OpenCBM (URL:, and the URL which you get if you click on my name). It implements a custom protocol via raw access to the parallel port.

    It might not be the best driver ever, but it works. 😉


    – strik

  325. gaurav_verma says:

    Hi doronh I am able to remap the serial port. Thanks to you (it was only because of your post in some other blog) that I founf the basics of port remapping.

    I have one more doubt i.e how to get the COM port number to which a serial mouse is connected?

  326. Otavio says:


    thanks for answering. I downloaded the code and at a first glance it is just what i need to know. Clear and well commented code. I’m going to look it deeply and use as base for my driver.

    thanks again,


  327. wtp says:


    For installing drivers which are signed with SPC certificates, on


    1) Do we need to ask users/clients to install the certificate on

    target machine?

    2) I have a certificate from Verisign. To which certificate stores

    should the users install the certificates on target machine?

    3) Is there a way to install certificates on target/client machines

    without user requiring to do it manually?


  328. KeenonK says:

    Hi doronh ,

    I’m a beginner in Device Driver Programing . I’ve implemented a small File system filter driver and consequently , i’m familier with Kernel mode programing . Today i want to have a device that can work with Physical Hard disk . The main point is that i want to read the HDD serial number , and , in order to do that i tried to open the physical Device by ZwCreateFile , some thing like this :

     if (Drive < ‘A’) swprintf (DriveName, L"\\.\HarddiskVolume%d", Drive) ;

     else             swprintf (DriveName, L"\DosDevices\%c:\", toupper(Drive)) ;

    RtlInitUnicodeString(&fileNameUnicodeString,(WCHAR *)DriveName);

     InitializeObjectAttributes( &objectAttributes, &fileNameUnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );

     ntStatus = ZwCreateFile( &hPhysicalDriveIOCTL, GENERIC_READ | GENERIC_WRITE ,

                 &objectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,


               NULL, 0 ) ;


    The "Drive" is an input  parameter .

    But it doesn’t work! what’s is wrong? the name of physical device or may be the ZwCreateFile parameters ?

    Help Plz…



  329. wtp says:

    Hi Doron,

    I have a basic doubt:

    Is it mandatory to use WDF (KMDF) to develop drivers for Vista 64 bits OS (also 32 bits OS)?

    Would drivers developed based on WDM (Windows Driver Model) compile & work fine?


  330. phasy says:

    Hello Doron,

    I want to customize MaximumTransferSize with KMDF for Win2k.

    (Because the default 4KB is too small for our USB device.) I think that there is a solution that mixes the code of WDM & KMDF.

    However, I want to know whether there is a solution that uses only KMDF. Could you teach?

    ex) the mixing code of WDM & KMDF.

    SelectInterfaces(IN WDFDEVICE Device)




     WdfUsbTargetDeviceSelectConfig( // snip



       urb = USBD_CreateConfigurationRequestEx( //snip


       Interface->Pipes[i].MaximumTransferSize = (256 * 1024);


       WdfUsbTargetDeviceSendUrbSynchronously( //snip






  331. phasy says:

    btw, there is the code


    in usbsamp.inx of the sample usbsamp of WDK6000.

    However, I believe that it doesn’t work.

    If it is correct, it might be comprehensible to delete it.


  332. Colin H says:

    Hi Doron,

    We’ve had previous experience developing BDA drivers, usually for USB-connected tv devices – essentially an avstream miniport driver. Planning a ‘next generation’ it seems that KMDF would clean up the USB side of things quite a bit, but is it in fact possible to create a BDA driver with KMDF or do we have to stick with the WDM route?



  333. doronh says:

    [I am writing the PCI bus storage WDM driver, and encountered a problem these days only in Vista. (the problem will not occur on XPSP2).  And the operation is "copying files to the storage device  (like MS/SD) , before finished, to enter power saving (sleep/Hibernet) mode, sometimes window will show error message as follow. error 0x800703EE: The volume for a file has been externally altered so that the opened file is no longer valid"]


    it depends on how deep in the storage stack you are.  If you are at the HBA level you must complete processing any i/os in progress and queue any new I/Os before powering down.  all of the storage drivers above the HBA assume that the HBA will deal with queue management with respect to power state.  If you use KMDF power managed queues, you get this behavior for free.


  334. doronh says:


    i am not sure i udnerstand what you are saying.  are you saying that both devices have the same serial number?  i have no idea of what you mean by resource reassignment at the usb layer.  usb devices consume endpoints, not hw resources.


  335. doronh says:

    kobi, I would need to see a callstack to make a guess as to what is going wrong.  BUT, PagedPool is not an infinite resource either and you will eventually hit the same constraints.


  336. doronh says:

    ComPort, TDI has a hard coded limit for the number of stack locations it uses when allocating IRPs.  I think the default max is 4, although there is a registry key to override this value.  Allocating a new sub irp for the incoming irps works if and only if you have a valid stack location for the current irp or you do not want to support cancelation.


  337. doronh says:

    torque, you can use KDMF to write a ramdisk (in fact there is a WDK ramdisk sample in WINDDK6000srckmdframdisk).  

    1)  KMDF still exists in the NT kernel and you must play by the rules that the NT kernel memory manager gives you.  If you can allocate 100 GB in a WDM driver, you can easily do the same in a KMDF driver.

    2)  by stick of RAM i assume you mean DRAM and not a USB Memory stick or something off the main mobo.  I do not think that the memory mamager allows for you to specify the physical addresses for an allocation, you might be able to play with a MDL and specify the physical addresses in the MDLs PFN list.  I have no idea what you mean about each CPU controlling some amount of memory.  CPUs do not own memory.


  338. doronh says:

    JohnnyLuo, do you want to change configurations on the fly at runtime?  or just at device plug in?   You can write a HID lower filter that changes the config descriptor index that the in box HID usb miniport driver requests and then it will use a different configuration, but this new configuration index must still match the USB HID specification in terms of endpoint usage.  

    Why does your device have so many configurations?


  339. DclsBOSS says:


    I can’t use DebugView on Vista x64…

    I saw your article:

    But I don’t understand the first step ^^

    Thank you for your explanation!


  340. DclsBOSS says:

    I add that my driver is a scanner minidriver…

    Thank you very much!

  341. DclsBOSS says:

    Well, we need to execute DebugView as Administrator…

  342. finewings says:

    Hi, Doron:

    Now I know that the SCRM will always open the smartcard reader and wait other process to connect the reader. So what is the sharing mode of the open operation by the SCRM. Is there a possibility that the reader be opened by another process? I want to have one process to simulate the "virtual smartcard", which will share the "virtual reader" with the SCRM. When SCRM transmit data to reader, my driver will copy the data to a shareable space where the virtual smartcard process can also access. The virtual smartcard fetch data there, process it and then write the result back.

    Is it possible to open one device twice?

    Do I need to register two different interface for the device?

    Is there any reference and samples about this topic?

  343. JohnnyLuo says:

    Hi doronh,

      I am writing a HID Mini driver for a scale platform, Since our platform have many kind of mode, for example, calibration, firmware,Differential weighting etc. So it have multiple configuration.I had replace the hidusb.sys with my own usb driver writen by KMDF. but when I try to select another configuration in my usb driver, it crash.

      And I also find some material said that the bus driver provided by Microsoft will select first configuration automatically, and the URB send to change the configuration will not be executed, is that correct?

    Thanks and regards

    Johnny Luo

  344. feretich says:

    Question regarding USB driver behavior:

    I am writing a Windows XP (& later) WDM kernel driver for a USB device. The device sends asynchronous messages from a bulk transfer endpoint. I am trying to keep a read operation posted continuously to this endpoint. There are two major questions for which I need to find answers to move forward on the design.

    Reads to this endpoint are accomplished via asynchronous Irps (created by IoAllocateIrp). If I receive certain messages, I need to quickly (in <8msec) send a message to a different endpoint. To meet this timing requirement, I have structured my ReadIrpCompletion routine (expected to be running at the DISPATCH_LEVEL) to:

    1) Parse the received message.

    2) If the message requires an immediate response, then start a write operation to the outbound pipe (this operation uses its own Irp.) by calling IoCallDriver with an appropriate URB.

    3) Then reissue the read for the next inbound message by calling IoCallDriver reusing the original URB and Irp.

    4) Perform some cleanup and queue management, then return STATUS_MORE_PROCESSING_REQUIRED.

    My questions are:

    1) When my ReadIrpCompletion routine reissues the read (step 3) is it possible that the lower level USB driver will call my ReadIrpCompletion routine to process the completion of the second read before it returns to me.

    2) At what point does the lower level USB driver throw away an inbound message? That is, if a new inbound message(s) arrives during step 1 or 2 will I receive it when I issue the read in step 3?


    Bob Feretich

  345. feretich says:

    After considering the problem for a day, I’m thinking that my best route is to have the ReadIrpCompletion routine reissue its Irp to read the next inbound message in a DPC. That way ReadIrpCompletion routine cannot be re-entered before it returns, thus making my design insensitive to the answers to the questions that I previously posed.

    I still would appreciate your thoughts though.


    Bob Feretich

  346. wtp says:

    I have signed my driver using Microsoft authenticode with test certificates.

    I have following 2 problems:

    1) On Windows XP, in the driver properties through Device manager, the

    ‘Digital Signer’ shows ‘Not digitally signed’. If I check the .sys

    file & the .cat files, they have a ‘Digital Signature’ tab containing

    appropriate signature. How do I get appropriate values for ‘Digital

    Signer’ property for the driver as well as the driver file.

    2) On Vista 64, Device manager->Driver properties displays appropriate

    ‘Digital Signer’. However, when ‘Driver Details’ button is clicked,

    for the driver file ‘Digital Signer’ displays ‘Not digitally signed’.

    How do I get the correct value for the driver files property?


  347. says:

    Hi Doronh,

    I have got this problem with DMA.

    My device DMA capabilities are

    1. Packet Based

    2. No ScatterGather Support

    3. Symultaneous Read & Write (Duplex) Operations

    4. 32 bit Addressing capability

    The Problem is since the device does not support ScatterGather , I have to go for

    "WdfDmaProfilePacket" option. If I take this option then I cannot take the full

    advantage of my device (Full Duplex) because only one Transaction can run at a time with this option.

    So, I tried to create two "WDFDMATRANSACTION objects" one Read and one for Write from two different

    "WDFDMAENABLER objects". Since transaction objects belongs to two different dmaenabler objects, I thought

    I can run two transactions at time because they belong to different dmaenbler objects. But I was getting this error

    "STATUS_WDF_BUSY". I failed to arrive at a proper solution. PLEASE HELP ME in this regard.

    Thank You,

    Kiran S

  348. buratino says:

    Hey Doron.

    I was wondering, if there is some way to unitest my driver,  running in user space.

    The best thing is some sort of environment which wraps the kernel side functions.

    I took a look at something called cxxtest (

    but it looks like the kernel side functions are not really called, they are just stubs and thus I’ll be missing my point.

    I’d rather not test my driver through black box testing, and was hoping you’d know of something ready.



  349. TBN says:

    Hi Doron,

    I made a USB device that identifies itself as a USB microphone via the ROM of the chip that I used (it’s the AK5371 stereo 16-bit A/D typically used for a USB microphone). I use the AK5371 to digitize data and I have a Windows MSVC++ 6.0 App that receives this data and processes it.

    This all works fine. (BTW, the chip uses usbccgp.sys and other MS WDM drivers when plugged – I don’t have/need a custom driver ).

    My next step is to use the USB 5VDC to power some external circuitry from this USB device. The problem is that the chip always reports 90mA as its maximum USB power requirement, and I have no way of controlling it. I need about 200mA total for this new application and I don’t want to use an external power source.

    My question is "How do I override the MaxPower value reported by the chip to allow more current-draw? Can I do it from my Windows App? Or, do I need my own custom USB driver (perhaps a filter driver to usbccgp.sys that intercepts the Configuration Descriptor)?"

    By the way, it appears that the 4 different PC’s I’ve tested (2 laptops on battery, 2 desktops) don’t even care about the MaxPower parameter and simply current-limit to about 1A with a dead-short on the 5V. I guess I don’t want a smart USB chip to bite me later…..

  350. taotal says:

    Hi Doron,

    we are developing Miniport (Wifi) driver  with Ndis 5 and Wdf.

    it seems that we have error to after we are starting continuous reader Pipe. something wrong with ep 0. (other wdf usbsmap – failed to read the descriptors, and got yellow band).

    can you explain how to operate continuousz reader with ndis 5? is it possible ?



  351. Dmitryg says:

    Hi, Doron.

    There is a function I was not able to find in the WDF DDK. How can a child object get a reference of it’s parent?

    Is it possible at all?

    I have a WDFMEMORY object and I want to retrieve it’s parent.


  352. buratino says:

    Hello Doron.

    I’m fairly new to driver writing.

    I’m trying to mount a Virtual Volume by using the non-PnP IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION to let the mount manager know a new volume has arrived.

    I tried mounting the volume over an existing virtual volume, so they’d have the same starting/end offsets and Physical target device to write to.

    I’ve implemented all of the REQUIRED mount manager client IOCTL responses and just about every other IOCTL I received during debug.

    I started getting read/write requests for the beginning of my virtual volume and then some random read requests I couldn’t make out (their destination was some where in the middle of my volume).

    I mounted my volume over an existing NTFS partition and over an existing FAT partition and there were some minor changes, but nothing seems to work.

    I can see that the Mount manager created a symbolic link to my volume,but I can’t access it.

    I believe that some upper FS driver reads data from the physical disk, , finds out that there is already a mounted device over it and ignores my volume.

    The entire issue is very poorly documented and I couldn’t find anything similar online.

    Have you ever dealt with this issue?

    Thanks a bunch,


  353. zorsoft says:

    Hi, Doron,

    Is true that the only proper way to write a NIC driver that uses NDIS and KMDF for USB to write two drivers (a KMDF USB driver with a NDIS Filter driver, similar to NDISEDGE over PCIDRV)?

    I think it is true for two reasons:

    1. It is not possible to create a pure KMDF driver inside of an NDIS driver since they both have competing initializaiton and framework requirements. (That is…it is possible to write WDM USB support in a NDIS driver, but not KMDF).

    2. To properly support Selective Suspend and have total control over power management, the USB driver has to have total control  over power events.

    Is what am I saying correct? I beleive it is, but people are telling me that it is possible to to write a monolithic NDIS that uses KMDF. I think you covered this topic above, but I want to make absolutely certain that this is the proper approach.

  354. RussMitch says:

    Hello Doron,

    I’m trying to convert a legacy device driver, which was created with BlueWater’s DriverWizard, to WDF.  The legacy driver creates MyDriverName.Raw & MyDriverName.Translated resources under MACHINEHARDWARERESOURCEMAPPnP ManagerPnpManager, but the WDF driver does not.  How do I make the WDF driver create these resources?


  355. says:

    Hello Doron,

    I am developing a USB Client WDM driver for XP. I am using the selective suspend mechanism for idle mode and also for Wait-Wake.

    The driver works fine but the problem is when I installed the driver in VISTA , the idle mode works but the Remote wake up is not happening. The bus driver is not completing the Wait-Wake Irp after the  reception of an extern signal. In WDK I found some details regarding the selective suspend enabling options (such as enabling the option in devicemanager ->USB Root hub ->properties-> power management ->Allow this device to turn off this device to save power). And also I enabled the option Control panel -> Power options -> Current "Power plan"->USB settings -> selective suspend and enabled all options (On Battery and Plugged In).

    Even after doing these, The Irp is not getting completed.

    What is the problem, Please help me in this regard.

    Thank You,

    Kiran S

  356. henrylin says:

    Hello Doron,

    I have a question about selective suspend and D2D3 issue.

    We develop Wireless LAN driver in Vista and encounter some challenge.

    Hope you can help me to solve.

    We use selective suspend function let device (our Wireless LAN card) enter D2 mode,

    Then we let system enter sleep (Start->Shut Down->Sleep).

    And wait a moment, we resume system.

    When system resume done, our device can not work (WLAN card can not scan to get AP list).

    In our WLAN driver, we can observe:

    When WLAN driver detects device is idle, then we call selective suspend function.

    The device power state will transfer from D0 to D2 (our WLAN driver MiniportPause will be called).

    Then WLAN driver detects device need to work, we call selective suspend function also.

    Then device power state transfers from D2 to D0 (our WLAN driver MiniportRestart will be called).

    It works fine.

    But if device power state transfers from D0 to D2, then we let system enter Sleep immediately (device power state will transfer from D2 to D3).

    When system resume, device power state transfers from D3 to D0 (our WLAN driver MiniportRestart will NOT be called). Device can not work.

    Could you help me power state transfers from D3 to D0, why our WLAN driver MiniportRestart does not be called?

  357. doronh says:

    henrylin, the problem here is that you are acting as the power policy owner (PPO) for the NDIS stack as an NDIS miniport when you are not actually the PPO!  You cannot manage the power state behind NDIS"s back like this because NDIS is not expecting random power irps to arrive outside of its own power logic.  

    My guess with your D3 to D0 transition is that the initial D2->D3 transition is incorrect and that you need to transition from D2 -> D0 -> D3 on resume.  If that does not help, you need to attach a kernel debugger and see where NDIS gets stuck.

    hth, d

  358. henrylin says:

    Dear Doron,

    thanks your response!

    Yes, i also want to let D2->D0->D3. But how to do ? When i press Start->Shut Down->Sleep. Our miniport driver handle OID’s code will be run(OID_PNP_SET_POWER). At this point device power state changes(i don’t know who changes this state, i guess is NDIS?) from D2 to D3. Could you tell me where to change state from D2 to D0 before someone changes devide power state from D2 to D3?



  359. henrylin says:


    Could you tell me where to change state from D2 to D0 before someone changes device power state from D2 to D3?

  360. doronh says:

    henrylin, this is one of the many problems trying to implement USB SS in a miniport where you are not the power policy owner.  In this case, the PPO does not track that the device is in Dx when it gets the Sx irp to it requests another Dx irp.

    How can you fix this?  Well you can register for an ex callback which tells you about the Sx/S0 transition before it is sent to the driver stacks.  I wrote about how to do this in this entry,  To get started, the docs on ExCreateCallback are here,  What you would do is disable USB SS and move back to D0 in the notification that the OS is going to Sx and then reenable the idling out (e.g. start your timer) when you get notified of going to S0.


  361. henrylin says:

    Dear Doron,

    Thanks your big big big support!!

    It works well.


  362. Kamala says:


    I hear Vista’s standard vga driver (vgapnp.sys) supports some level of power management.  I would like to know what that "some level" is.  Powercfg -a when run under Vista (standard vga enabled) complains that vgapnp does not allow certain Sx transitions like S2, S3 etc.  Is there a way to stop vgapnp.sys from impeding S2, S3 transitions?

    Switching to a vendor specific video driver though an obvious option is not what I am looking for.  I would like to use standard vga if possible inspite of obvious drawbacks.



  363. doronh says:

    Kamala, i asked around.  vgapnp.sys supports hibernate, but that is it.  it does not support S1-S3 due to varying BIOS compat problems that were encountered during test.


  364. Kamala says:

    Thanks for getting back!


  365. Eric93 says:

    Hi, Doran:

    I am NDIS WLAN driver developers, there is a problem while we are calling a WDF function, and hope you can give us some advices:

    When the driver calls WdfIoTargetStop( WdfUsbTargetPipeGetIoTarget(pDevice->InterruptPipe) , WdfIoTargetCancelSentIo)  to stop I/O in USB device  in a workitem,  sometimes ( around 1/20 ) this function does not return, and this will lead to the whole driver hangs.

    The device has 4 pipes: Interrupt, Control In, Bulk In and Bulk Out.  The Interrupt pipe is continous reader.

    Driver uses 3 WDF requests for Interrupt, Bulk In, and Bulk Out pipes :

    For Interrupt: WDF continuously read from a specified USB pipe.

    For Bulk In: WDF read request for a USB input pipe(formated with WdfUsbTargetPipeFormatRequestForRead()).

    For Bulk Out: WDF write request for a USB output pipe(formated with WdfUsbTargetPipeFormatRequestForWrite())

    The reason why the driver call WdfIoTargetStop() is that we want to call WdfUsbTargetDeviceResetPortSynchronously() to reset USB port when transaction error occurred on USB bus.  BeforeWdfUsbTargetDeviceResetPortSynchronously() , we call WdfIoTargetStop() to stop all queued I/O request.

    Through experiments, we found that the probability of WdfIoTargetStop() doesn’t return issue might be reduced after all BulkIn and BulkOut WDF requests to be completed.

    The code slice is below:


    call WdfUsbTargetPipeAbortSynchronously() to abort BulkIn and BulkOut pipe;

    wait all BulkIn and BulkOut WDF requests to be completed(completion-routines returned).





    Through experiments, we found the while loop that waits for Completions might reduce the probability that WdfIoTargetStop() is not returning.

    Is there any prerequisite for calling WdfIoTargetStop()?

    Do you have any clue about why is WdfIoTargetStop() not returning?

    Thanks in advance.

  366. wind2000 says:

    Hi Doran…

    i’m currently doing a project of USB Mass Storage Acces Control System where we can block the usb devices…

    can u pls tell me how to trap the messages sended by usb Mass storage devices using windows hooks…

    Does the service can handle it without using hooks…

    How to programatically make a USB mass storage Device write protected…

    I’m new to win32API so can u guide step by step to solve these problems…

    Thanks in advance…

    varun 🙂

    Thanks in advance…


  367. nkobik says:

    Hi doron.

    i have an architecture question regarding a communication between two drivers, one of them is WDF based and the other isn’t.

    these two driver needs to communicate with each other. i’ve implemented the communicaiton methods using interface notification registration for synch ussues and function pointers that are passed between the drivers in order to implement the actual communication.

    now – DriverB (non wdf) is in charge of the interrupt handling. within its DPC it calls functions that are implemented in driverA (WDF based). it works fine and i can pass data between the two drivers.

    now, here is my problem. upon interrupt, driverB(non wdf) will call a method(through a function pointer) in driverA(WDF).  in this method (implemented in the WDF drievr but called from the non-wdf driver) i would like to complete a pending IOCTL that was previously sent to driverA(WDF).  since my call to the method was from the nonWDf driver, i can’t complete the pending IOCTL since i can’t call any WDF method. what are my options in that case to do so ?  can DriverB(non-WDF) triger an event to wake a thread in driverA(WDF) to complete the IRP ?  



  368. vookimedlo says:

    Hi Doron,

    I’d like to ask you about WdfTimerStop function.

    When the ‘Wait’ parameter is set to FALSE, does it mean that all queued calls fired by timer are canceled? If not, how can I cancel them?

    Thanks in advance.


  369. himanshup123 says:

    Hi Doron,

    I wish to intercept or monitor the file io as well as network io. i am sure that if i write a file system filter driver, i will be able to monitor file io. 🙂

    But will ‘redirector’ sends networking related apis also to my filter driver. if not..

    can u suggest me a better technique to do monitoring of file io and networking io.

    thanks in advance.


  370. eranb says:

    Hi Doron,

    I’v been pokling around WDF headers to see what is the internal implementation of WDF context objects and how does WDF work in order to make context object retrieval fast. However, the headers don’t tell the whole story. I was wondering if you can give a post describing the context object infrastructure, and the way the internals are designed to be able to retrieve any type of context object from a WDF handle in a fast way.



  371. vijayprasads says:

    Hi Doron,

    I am developing a miniport storage driver for HBA. I am trying to write Event Log other than SCSI events. ScsiPortLogError or StorPortLogError functions are used to log only the SCSI events. For my requirement I have to use IoAllocateErrorLogEntry & IoWriteErrorLogEntry functions. IoAllocateErrorLogEntry takes DriverObject as input. In miniport driver, we can get DriverObject only in DriverEntry function. Is it good to save this pointer for future usage for writing events. Or if there is any other way to write event log messages plz post it.



  372. nkobik says:

    Hi Doron,

    i have a case of a bug check that is issued occasionaly and specifies the pci.sys as the faulting driver.

    I’m using a routine which uses "IRP_MN_READ_CONFIG/IRP_MN_WRITE_CONFIG"  in order

    to write/read pci configuration space of a device.

    on earlier days i used HalGetBusData/HalSetBusData but now that they are obsolete i’m using an irp as described before (as documented in the MSDN).

    as a result of this call i sometime get the bugcheck and i can’t expect when the bug check will be issued or not.


    bug check parameters :


    any idea ?


    it might sound strange but here’s another piece of information :

    on my machine there’s an antivirus client (symantec). somehow, but i can’t be 100% sure, while the antivirus client is up the bugcheck will be issued. when it’s service is down the bug check will not occur.



  373. deivi says:

    Dear Doronh!

    I haven’t found anything related to how to setup alternate settings for a multi interface usb driver.


    if (numInterfaces == 1){



    else {

       settingPairs = ExAllocatePoolWithTag(


                           sizeof(WDF_USB_INTERFACE_SETTING_PAIR) * numInterfaces,



       if (settingPairs == NULL){














    status = WdfUsbTargetDeviceSelectConfig(





    But I don’t know what InitSettingPairs should do?

    I hope you could give some directions about how to setup a multiple interface device that uses alternate settings for increasing bandwidth.


  374. dreamgate says:

    Hi Doron,

    I am a NDIS USB WLAN driver developer.Our driver must support selective suspend to let CPU enter C3/C4 state. We port the selective suspend feature from XP DDK sample code to our miniport driver, and then we can let CPU enter C3 state when USB is idle. But the selective suspend feature can not let CPU enter C4 state. Could you please let me know how to let CPU enter C4 state? thanks.

  375. hrvd says:

    Hi Doron,

    I’ve installed the NDIS MUX sample, and want to develop a command line tool to create / remove VLANs for the specified physical NIC.

    I can trigger the install from my command line tool, and modified the notifyob DLL to add the new miniport to the first physical adapter available. This seem to be working fine.

    My question is if there are more than one physical NICs, and I want to create a virtual NIC on the second/third physical NIC, is there a way to indicate that to the notifyob DLL?



  376. deivi says:

    Hi Doron

    I’m having problems with a driver based on usbsamp. I’m trying to do simultaneous read and write in the Bulk Endpoints. I have separated threads for this in the user app.

    The problem is that some writes makes the outstanding read to return with a STATUS_UNSUCCESSFUL (0xC0000001) code.

    I like to know what could be the cause of this. Or if the sample is designed to support simultaneous reads/writes or not. Are there some synchronization issues I should be aware of? And why does the driver tries to reset the pipe after failure? Is this completely necessary?


    David M.

  377. grace.79 says:

    Hi Doron,

    I wrote a KMDF driver for a PCI device. I have to use "WdfDeviceCreateDeviceInterface" to create a Interface with a "ReferenceString". This "ReferenceString" is determined by the PCI device’s curent state. So I do "WdfDeviceCreateDeviceInterface"  and write some information into registry in "EvtDeviceD0Entry". It can work in most time except OS is restarted. After I change the PCI device’s state, I restart OS(WinXP). After OS restart, I find no new information written to registry. If I disabel this PCI device and enable this PCI device again, the new information can be writen to registry.

    Can you give me any suggestions or tips?Thanks a lot!

  378. lokeshp says:

    Hi ?Doron

    I am trying to get and set the properties of soundmax card.Both get and set uses deviceiocontrol.The get version is working fine but when i set the pin state to RUN ,the deviceiocontrol fails returning error ERROR_BAD_COMMAND.There are two kinds of cards on my m/c.One is soundmax and the other maudio.For maudio it works fine but it fails for soundmax.I am running vista on my m/c.

    I am calling deviceiocontrol twice one after other for get and set.Can you pls let me know why it fails for second time.

  379. vanim says:

    Hi Doran,

    Task : Virtual COM port Driver

    OS : windows XP using kmdf

    Steps for Creating a virtual COM port.

    using the toaster sample function driver:

    a)modified wdfsimple.inf to install a COM port by assigning

    class = ports

    ClassGuid = {guidOfSerial}

    installed as a root-enumerated device.

    a) Modified the evtDeviceAdd to create a Symbolic link, added the registry entry under HKLMxx so that hyperterminal or other apps can see this virtual port

    registered the DeviceInterface(GUID_DEVINTERFACE_COMPORT

    b)EvtIoRead & EvtIoWrite are currently dummy.

    Here i intend to pass the data to the bluetooth driver.

    c) in EvtIodeviceControl added basic handling for Get/Set of baud Rate /Line Status

    Apart from the IOCTL handling , is ther any other Events which my virtual Serial Port Driver should handle?

  380. StevenChen says:

    Hi Doran,

      I’m sorry for my English and new in program. I hope my description won’t confuse you.

    I’m developing an application with USB device scan.

    Using WM_DEVICECHANGE , I retrieved the Symbolic Link of device.

    Is there a methord that retrieved the device descriptor of this USB device through the Symbolic Link of device?

    I have read the USBView sample in DDK, that methor costs too much time to retrieved the device descriptor. Also, driver of this device doesn’t support the function.

    Looking forward to your reply!Thank you!

  381. PramodK says:

    Dear Doran

    Greetings !

    I am developing a driver for Ethernet over USB in Win XP. I registered the read write calls in the AddDevice() as follwos :

    In USBSamp the registration of the callback function is done as :




    WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &fileObjectAttributes);

    I am using NDIS-WDM as Upper edge and USBsamp as Function driver. I am able to send IRP_MJ_WRITE event to USB driver which in turn invokes EvtIoWrite callback function properly. EvtIoWrite invokes WdfRequestGetFileObject()  Which returns NULL.  This is possiblly because USB driver did not receive IRP_MJ_CREATE to create FILE OBJECT. Then i inserted IRP_MJ_CREATE event in my NIDS driver as follows :

    PIRP irp = Adapter->StatusIndicationIrp;


    DEBUGP(MP_INFO, ("–> NICPostAsynchronousStatusIndicationIrpn"));

    IoReuseIrp(irp, STATUS_SUCCESS);

    nextStack = IoGetNextIrpStackLocation( irp );

    nextStack->MajorFunction = IRP_MJ_CREATE ;

    nextStack->FileObject = Adapter->FileObject;

    IoSetCompletionRoutine(irp, NICStatusIndicationCreateIrpCompletionRoutine, Adapter, TRUE, TRUE,TRUE);

    Adapter->StatusIndicationIrpLock = IRPLOCK_CANCELABLE;


    (void) IoCallDriver(Adapter->TargetDeviceObject, irp);

    However, this call also fail’s in the COMPLETION ROUTINE  at

    if(!NT_SUCCESS(Irp->IoStatus.Status)). With Status code 0xc0000182

    Can you help me in the right implementation of IRP_MJ_CREATE or an appropriate solution for WdfRequestGetFileObject() in the EvtIoWrite routine to Pass.

    Kindly guide me in resolving this issue.

    With Warm Regards,

    Pramod Kolhapure

  382. Alex_P says:

    Hi Doron,

    I am writing a KMDF driver for my USB device. The device transfers data via bulk pipe to the PC. For this I am using the continuous reader feature on the WDFUSBPIPE. I am aware that there is a limit on number of transfers (max 10), but nowhere could I find the limit on the transfer size. It seems that this is under Windows 7 about 512K. If I set it to anything larger I get the BSOD. It also seems that there is some kind of limit based on the number_of_transfers*transfer_size. Could you explain these limits in some detail please.

    Best Regards,