Flylib.com

Books Software

 
 
 

Code Example: Driver Unload

< BACK    NEXT  >
[oR]

Code Example: Driver Unload

In the Minimal driver, an Unload routine is supplied that undoes the work of DriverEntry. Its work is straightforward, as it must delete each symbolic link and device object that has been created. To perform this work, the Unload routine relies on the fact that the driver object points to a linked list of device objects controlled by the driver.

The first device controlled by a driver is pointed to by the field DeviceObject within the driver object. Each device points to the next via the field NextDevice . When examining the Unload routine, remember that the Minimal DEVICE_EXTENSION structure maintains a back pointer to the parent device object.

//++
// Function:  DriverUnload
//
// Description:
//        Stops & Deletes devices controlled by this driver.
//        Stops interrupt processing (if any)
//        Releases kernel resources consumed by driver
//
// Arguments:
//        pDriverObject - Passed from I/O Manager
//
// Return value:
//        None
// -

VOID DriverUnload (
          IN PDRIVER_OBJECT pDriverObject ) {
          
     PDEVICE_OBJECT pNextObj;
     
     // Loop through each device controlled by Driver
     pNextObj = pDriverObject->DeviceObject;
     while (pNextObj != NULL) {
          // Dig out the Device Extension from the
          // Device Object
          PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
               pNextObj->DeviceExtension;
          // This will yield the symbolic link name
          UNICODE_STRING pLinkName =
               pDevExt->ustrSymLinkName;
          // ... which can now be deleted
          IoDeleteSymbolicLink(&pLinkName);
          // a little trickery...
          // we need to delete the device object, BUT
          // the Device object is pointed to by pNextObj
          // If we delete the device object first,
          // we can't traverse to the next Device in the list
          // Rather than create another pointer, we can
          // use the DeviceExtension's back pointer
          // to the device.
          // So, first update the next pointer...
          pNextObj = pNextObj->NextDevice;
          // then delete the device using the Extension
          IoDeleteDevice( pDevExt->pDevice );
     }
     // Finally, hardware that was allocated in DriverEntry
     // would be released here using
     // IoReportResourceUsage
}
< BACK    NEXT >
< BACK    NEXT >
[oR]

Writing Shutdown Routines

If a driver has special processing to do before the operating system disappears, a driver should supply a Shutdown routine.

Execution Context

The I/O Manager calls a Shutdown routine during a system shutdown. As described in Table 6.5, the Shutdown routine runs at PASSIVE_LEVEL IRQL, which means it has access to paged system resources.

Table 6.5. Function Prototype for Shutdown Routine
NTSTATUS Shutdown IRQL == PASSIVE_LEVEL
Parameter Description
IN PRDRIVE_OBJECT pDriverObject Pointer to driver object for this driver
IN PIRP pIrp Pointer to shutdown IRP
Return value • STATUS_SUCCESS -or-
  • STATUS_XXX - some error code

What a Shutdown Routine Does

The main purpose of the Shutdown routine is to put the device into a quiescent state and perhaps store some device information into the system Registry. Again, saving the current volume settings from a sound card is a good example of something a Shutdown routine might do.

Unlike the driver's Unload routine, Shutdown routines don't have to worry about releasing driver resources because the operating system is about to disappear anyway.

Enabling Shutdown Notification

There is no direct field in the Driver object for announcing the Shutdown routine. Instead, the event of system shutdown is sent as a separate I/O request to a driver. It is handled with an entry inside of the driver's MajorFunction code array.

Additionally, the I/O Manager must be notified that a driver is interested in receiving shutdown notifications. This is done by making a call to IoRegisterShutdownNotification . The following code fragment shows how to enable shutdown notifications in a driver.

NTSTATUS DriverEntry (
     IN PDRIVER_OBJECT pDriverObject,
     IN PUNICODE_STRING pRegistryPath ) {
     :
     pDriverObject->MajorFunction[ IRP_MJ_SHUTDOWN ] =
               Shutdown;
     IoRegisterShutdownNotification( pDriverObject );
     :
}
< BACK    NEXT >