5.1.1 Every DriverEntry Routine’s Responsibilites
Every DriverEntry routine is run in the context of a system thread at IRQL PASSIVE_LEVEL.
In general, a DriverEntry routine is responsible for exporting the driver’s other entry points, for initializing the NT objects the driver uses, and for setting up any other system resources that the driver uses. For more information about NT objects, see Chapter 3.
A DriverEntry routine can use the Windows NT® registry to get some of the information it needs to initialize the driver or its device(s). The DriverEntry routine must set information in the registry for other NT drivers and/or protected subsystems to use. For more information about using the registry, see Chapter 16.
In particular, every DriverEntry routine must do the following:
·Fill in the driver object entry points for the driver’s Dispatch, StartIo (if any), and Unload (if any) routines.
See Chapter 2 for how to do this. For more information about Dispatch, StartIo, and Unload routines, see Chapters 6, 7, and 15, respectively.
·Create a named device object to represent each physical, logical, or virtual device for which the driver handles I/O requests.
See Chapter 3 for how to set up a device object.
·Claim any necessary hardware resources or find appropriate lower-level drivers in the registry, and set up any necessary symbolic links between the names of the driver’s device objects and the Win32® subsystem names for the same devices. The I/O Manager provides support for setting up these symbolic links.
See Chapter 16 for more information about using the registry and setting up symbolic links.
·Register the driver’s other entry points and set up the NT objects necessary for any other standard routines the driver has.
For routine-specific requirements, see Chapters 7-9, 11, and 14.
·Create and/or initialize any other NT objects, types, or resources the driver uses, such as the following:
·If the driver has a device-dedicated thread or waits on any Kernel-defined dispatcher objects, the DriverEntry routine must initialize the dispatcher object(s) that its thread or the driver waits on by calling the appropriate KeInitializeXxx support routine with a pointer to the event, semaphore, mutex, and/or timer object(s) for which the driver provides the storage.
Because it executes in a system-thread context, the DriverEntry routine itself can wait for a nonzero interval on a dispatcher object, which must be initialized before the wait begins. For example, class drivers that call down to a corresponding port driver during initialization usually wait on an event object they associate with an IRP, which they allocate with IoBuildSynchronousFsdRequest and pass with IoCallDriver to the port driver for the physical device.
See Chapter 3 for more information about waiting on dispatcher objects.
·If the driver uses any executive spin lock(s) or provides the storage for an interrupt spin lock, the DriverEntry routine must call KeInitializeSpinLock with each such spin lock before passing it to any other support routine.
See Chapter 16 for guidelines on how to use spin locks, and Chapter 8 for more information about whether a device driver must supply storage for an interrupt spin lock.
·Return NTSTATUS indicating whether the driver can accept and successfully process I/O requests for at least one named device object that the driver created.
Return from DriverEntry
As shown by its declaration, a DriverEntry routine returns an NTSTATUS-type value. The DriverEntry routine should postpone any call to IoRegisterDriverReinitialization until just before it returns STATUS_SUCCESS. It must not make this call unless it will return STATUS_SUCCESS.
If a DriverEntry routine returns something other than STATUS_SUCCESS to indicate that it can successfully process I/O requests for at least one named device object that it created, that driver does not remain loaded.
A DriverEntry routine that will fail initialization must free any NT objects, system resources, and registry resources it has already set up before it returns control. It should reset the driver’s Dispatch entry points in the driver object for IRP_MJ_FLUSH_BUFFERS and/or IRP_MJ_SHUTDOWN to NULL if the driver supports these requests. If it already called IoRegisterShutdownNotification, the DriverEntry routine must call IoUnregisterShutdownNotification before it fails initialization.
If a driver will fail initialization, the DriverEntry routine also should log an error or have IoReportResourceUsage log a hardware resource conflict error on a device driver’s behalf before DriverEntry returns control. For more information about logging I/O and resource-conflict errors, see Chapter 16.