5.3 Reinitialize Routine Requirements and Functionality
Like the DriverEntry routine, a Reinitialize routine is run in a system thread context at IRQL PASSIVE_LEVEL.
If an NT driver cannot fully initialize itself in its DriverEntry routine, it can supply a Reinitialize routine to be called some time after its DriverEntry routine returns control.
For example, the NT fault-tolerant disk driver, ftdisk, is loaded very early in the boot process in case its support is needed to boot the system from a mirrored partition. When the ftdisk driver's DriverEntry routine is called, it can layer the ftdisk driver only over driver(s) for the device from which the system image is loaded. Consequently, the ftdisk driver has a Reinitialize routine to be called later in the boot process after all other lowest-level mass storage device drivers (and any drivers layered above them but below the ftdisk driver) have initialized and been loaded. This driver's Reinitialize routine layers the ftdisk driver over the remaining drivers of devices that have mirror sets, stripe sets, or volume sets by attaching ftdisk-created device objects to the lower drivers' device objects, as mentioned in Section 5.2.2.
If an NT driver has a Reinitialize routine, its DriverEntry routine causes the Reinitialize routine to be run later by calling IoRegisterDriverReinitialization once. The DriverEntry routine is responsible for setting up any context data to be passed to the Reinitialize routine before it calls IoRegisterDriverReinitialization.
If its Reinitialize routine uses the registry, the data at Context might include the RegistryPath pointer that was passed to the DriverEntry routine because this pointer is not an input parameter to the Reinitialize routine, as shown by its declaration. For more information about using RegistryPath, see Chapter 16.
The DriverEntry routine can call IoRegisterDriverReinitialization only once. If the Reinitialize routine should be run again after any other drivers' Reinitialize routines have returned control, the Reinitialize routine also can call IoRegisterDriverReinitialization as many times as the driver's Reinitialize routine should be run. The Count passed to the Reinitialize routine indicates how many times this routine has been called, including the current call.
Note also that a driver's Reinitialize routine should not be registered unless its DriverEntry routine will return STATUS_SUCCESS, indicating that the driver has successfully set up at least one named device object representing an initialized physical device or a logical/virtual device for which it can process I/O requests.
Usually, a driver with a Reinitialize routine is a higher-level NT driver that has already layered itself over at least one underlying device driver in its DriverEntry routine. Such a higher-level driver has already created at least one device object, but might need to create others to layer itself over additional chains of NT drivers for an underlying device of the same type. Consequently, such a driver's Reinitialize routine initializes in the same basic stages, already described in Section 5.2.2, and has the same basic requirements as its DriverEntry routine, except that it does not return an NTSTATUS value.
If an NT device driver has a Reinitialize routine, it initializes in the same basic stages, already described in Section 5.2.1, and it also has the same basic requirements as its DriverEntry routine.
Note that if a device driver postpones making claims on some hardware resources in the registry to its Reinitialize routine, many other NT device drivers might load in the interval between when the driver returned control from DriverEntry and when its Reinitialize routine is called. These other device drivers will then have already claimed their respective hardware resources in the registry, so such a device driver's Reinitialize routine might have difficulty claiming all hardware resources that the driver needs to initialize additional physical devices.