In this article, I want to discuss why drivers fail to unload. Failure to unload a driver leads to poor user-experience because the system needs to be rebooted either to update the driver or to make the device functional if the user plugs the device again. At the bottom of this article, I have pointer to other articles that describe how to avoid system reboots. Here, I'm want to provide insight into how the OS unloads a driver and what would prevent a driver from unloading.
Developers generally assume that if the DriverUnload routine is called then the driver-unload process is complete and driver should have unloaded. This is not true. Invocation of DriverUnload routine and the unloading of driver-image from memory is a two separate process governed by different factors in the system. In the first step, the system makes an attempt to unload the driver by calling the registered DriverObject->DriverUnload routine. When the DriverUnload routine returns, the system drops the final reference on the driverobject to trigger unloading of driver-image from memory.
So for a driver image to unload two things need to happen:
So deleting deviceobjects is key to get getting driver-unload to succeed. To understand the mistakes that prevent driver unload, let me categorize device drivers, based on when and how deviceobjects are created, into 3 types: legacy driver, pure pnp driver, and hybrid driver:
Let us understand how these 3 types of drivers unload:
Quite a number of you write such hybrid drivers, especially in stacks where the upper drivers don't allow unknown ioctls to pass-down (e.g keyboard class driver). Windows 7 WDK contains a filter sample (both in WDM and KMDF) as part of toaster package that shows to safely handle this situation. Since KMDF has made it easy to write a bus driver, we suggest even a simpler solution to have sideband communication. That is by enumerating a child-device for every pnp-device your driver attaches to. This enables you to have to one-to-one sideband communication relationship with the pnp device. This technique is also illustrated in another sample (kbfiltr) in the WDK.
Application, services and other kernel-mode clients failing to close handle to the device when the device is being removed is another common source of driver unload problem. Whenever a client opens a handle to a pnp device, it should register for pnp notification and close the handle when the system notifies the device is being removed. There are samples in the WDK that shows how to do from an application, service and a device driver.
Let me briefly touch upon some debugging techniques to root-cause driver unload problem.
Summary
List of primary reasons for a driver to fail to unload:
List of rules to remember when trouble shooting a driver unload issue:
More information to avoid reboots during driver install: