Releasing Device and Controller Objects
Before a driver deletes a device or controller object, it must release its references to external resources, such as pointers to other drivers' objects or to interrupt objects, that it stored in the corresponding device or controller extension. It can then call IoDeleteDevice for each device object that the driver created. A non-WDM driver that previously called IoCreateController must also call IoDeleteController.
Any Kernel-defined object for which the driver provides storage in a device extension is automatically freed when the Unload routine calls IoDeleteDevice with the corresponding device object. In general, any object that the DriverEntry or Reinitialize routine set up by calling KeInitializeXxx can be freed by a call to IoDeleteDevice if the driver provided storage for that object in its device extension. For example, if a driver has a CustomTimerDpc routine and has provided storage for the necessary DPC and timer objects in its device extension, the call to IoDeleteDevice releases these system resources.
Similarly, any Kernel-defined object for which the driver provides storage in a controller extension is automatically freed when the Unload routine calls IoDeleteController with the corresponding controller object.
If the DriverEntry or Reinitialize routine called IoGetConfigurationInformation to increment the count for a particular type of device, the Unload routine also must call IoGetConfigurationInformation and decrement the count for its devices in the I/O manager's global configuration information structure as it deletes the corresponding device objects.
Before it returns control, an Unload routine also is responsible for freeing any other driver-allocated resources that have not yet been freed by other driver routines.