Debugging a Failed Driver Unload
A driver will not unload if there is a leaked reference to DeviceObject or DriverObject. This is a common cause of failed driver unloads.
Apart from IoCreateDevice, there are several functions that take reference to DriverObject and DeviceObject. If you do not follow the guidelines for using the functions, you will end up leaking the reference.
Here is an example of how to debug this problem. Although DeviceObject is used in this example, this technique works for all objects.
Fixing a driver that fails to unload
Put a breakpoint right after the driver calls IoCreateDevice. Get the DeviceObject address.
Find the object header by using the !object extension on this object address:
kd> !object 81a578c0 Object: 81a578c0 Type: (81bd0e70) Device ObjectHeader: 81a578a8 HandleCount: 0 PointerCount: 3 Directory Object: e1001208 Name: Serial0
The first variable in the ObjectHeader is the pointer count or reference count.
Put a write breakpoint on the pointer count, using the ObjectHeader's address:
kd> ba w4 81a578a8 "k;g"
Use g (Go). The debugger will produce a log.
Look for the mismatched reference/dereference pair -- specifically, a missing dereference. (Note that ObReferenceObject is implemented as a macro inside the kernel.)