📄 driver.cpp
字号:
// Driver.cpp -- Driver object management for STUPID.SYS (DFW version)
// Copyright (C) 2003 by Walter Oney
// All rights reserved
// STUPID.SYS is the simplest possible framework-based driver. It creates
// a DFWDRIVER object and relies on the framework to handle all aspects of
// interfacing with the PnP and Power Managers -- including creating a
// DFWDEVICE object in the AddDevice function. You should be able to install,
// disable, enable, and uninstall one or more STUPID devices and to put the
// computer through power cycles with them installed.
#include "stddcls.h"
#include "driver.h"
#include "version.h"
DFWSTATUS EvtDriverDeviceAdd(DFWDRIVER hDriver, DFWDEVICE hDevice);
VOID EvtDriverUnload(DFWDRIVER hDriver);
////////////////////////////////////////////////////////////////////////////////
// DriverEntry creates and initializes a framework driver object. This function
// is called at PASSIVE_LEVEL without any presentation lock and can therefore be
// kept in paged memory.
#pragma PAGEDCODE
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{ // DriverEntry
PAGED_CODE();
// This driver uses DfwTraceDbgPrint to print a few debugging messages,
// but best practice would be to use WPP tracing instead. Next best
// would be to call DfwTraceMessage (which goes only to the trace log)
// and DfwTraceError (which goes both to the trace log and to the
// debugger if the DbgVerifierDbgPrintOn option is set).
DfwTraceDbgPrint(DRIVERNAME " - Version %d.%2.2d.%3.3d, %s %s\n",
VERMAJOR, VERMINOR, BUILD, __DATE__, __TIME__);
// Setup a driver configuration structure for use as a parameter to a
// call to DfwDriverCreate. We could use the DFW_DRIVER_CONFIG_INIT
// macro to help us do this, but (frankly) it doesn't add much value
// over and above a C-standard initializer. For expository purposes,
// I'm using explicit assignment statements here to do the initialization.
// Note that the compiler would generate basically the same code for
// the DFW_DRIVER_CONFIG_INIT macro, a complete declaration with
// initializer, and the following. Note also that the presence of any
// initializer causes the compiler to zero-initialize the remainder of
// the structure.
DFW_DRIVER_CONFIG config = {sizeof(DFW_DRIVER_CONFIG)}; // Size -- the size of the structure
// DeviceExtensionSize is the size of the device extension structure
// that the framework will allocate for each DFWDEVICE created by this
// driver. More complex drivers would have a non-empty extension. Still
// more complex drivers might be creating different types of
// device object by calling DfwDeviceCreateChild or DfwDeviceCreateControlObject,
// either of which has an extension-size argument.
config.DeviceExtensionSize = 0;
// RequestContextSize is the size of an optional context structure that
// the framework will create for each DFWREQUEST (i.e., IRP). This
// driver doesn't explicitly handle any IRPs, so this might as well be zero.
config.RequestContextSize = 0;
// Events contains pointers to "event" callback routines. A driver object
// has two events: DeviceAdd (formerly known as AddDevice) and Unload
// (formerly known as DriverUnload). The DeviceAdd callback is required,
// even if it doesn't do anything except initialize a DFWDEVICE object with
// default parameters.
config.Events.EvtDriverDeviceAdd = EvtDriverDeviceAdd;
// An Unload event callback would be needed only to undo any side effects
// of this DriverEntry routine. There are none in this driver, so we could
// leave out this callback. I like to see a debug message to tell me that
// a driver has really unloaded, however, so I'm specifying that callback:
config.Events.EvtDriverUnload = EvtDriverUnload;
// No bits had been defined in DriverInitFlags at the time I wrote this
// sample...
config.DriverInitFlags = 0;
// The LockingConfig specifies the synchronization behavior for the
// whole driver. Since this driver doesn't actually do anything, it
// hardly matters what we specify here. A plausible choice when you're
// just starting out is DfwLockingDevice, in which the framework
// serializes calls to all callbacks related to a particular device
// object by using a per-device "presentation" lock.
config.LockingConfig = DfwLockingDevice;
// The ThreadingConfig specifies whether event callbacks to this driver
// should be allowed to block their calling thread (synchronous) or
// not (asynchronous). The preferred choice is asynchronous, which implies
// use of a spin lock to synchronize event callbacks at DISPATCH_LEVEL.
// Note that this behavior is quite a bit different than the regular WDM
// model, in which driver routines can be called at several different IRQLs
// and must synchronize using IRQL-appropriate locks.
config.ThreadingConfig = DfwThreadingAsynchronous;
// SynchronizationConfig is intended to specify how this driver synchronizes
// hardware access. There is currently just one choice (None), which implies
// that the driver has to do it's own interrupt synchronization. There may
// someday be another choice for DIRQL-level synchronization as with a WDM interrupt object.
config.SynchronizationConfig = DfwSynchronizationNone;
// Invoke DfwDriverCreate to create a framework driver object. The
// third parameter to this function -- NULL in this example -- is
// the address of an optional DFW_OBJECT_ATTRIBUTES structure that
// could be used to specify a context-structure size and a destruction
// callback. These things would be useful, perhaps, in a single-device
// driver that kept all of its state information in a "driver extension"
// structure that needed cleanup. I'm hard pressed to think of a situation
// when I'd want to use them, though, given that there is an Unload callback.
DFWDRIVER Driver;
DFWSTATUS status = DfwDriverCreate(DriverObject, RegistryPath, NULL,
&config, &Driver);
if (!NT_SUCCESS(status))
DfwTraceError(DRIVERNAME " - DfwDriverCreate failed - %X\n", status);
// Return the status code from DfwDriverCreate.
return status;
} // DriverEntry
////////////////////////////////////////////////////////////////////////////////
// The framework calls EvtDriverDeviceAdd to initialize a new device object.
#pragma LOCKEDCODE
DFWSTATUS EvtDriverDeviceAdd(DFWDRIVER hDriver, DFWDEVICE hDevice)
{ // EvtDriverDeviceAdd
DfwTraceDbgPrint(DRIVERNAME " - EvtDriverDeviceAdd entered - IRQL is %d\n", KeGetCurrentIrql());
DFWSTATUS status;
// In a more complex driver, we would do many things in this function. For example,
// prior to calling DfwDeviceInitialize, we might:
// .Call DfwDeviceSetDeviceName to establish the name for the DEVICE_OBJECT
// .Call DfwDeviceSetDeviceType to establish the type for the DEVICE_OBJECT
// .Call DfwDeviceSetDeviceCharacteristics to establish the characteristics flags for the DEVICE_OBJECT
// .Call DfwDeviceSetExclusive to establish the Exclusive flag to be used in the eventual call to IoCreateDevice.
// DfwDeviceInitialize will, among other things, call IoCreateDevice.
status = DfwDeviceInitialize(hDevice);
if (!NT_SUCCESS(status))
{
DfwTraceError(DRIVERNAME " - DfwDeviceInitialize failed - %X\n", status);
return status;
}
// In a more complex driver, we might now do these additional things:
// .Call DfwDeviceCreateDeviceInterface to register a device interface GUID.
// .Call one or more functions like DfwDeviceRegisterCallbacks to establish
// event callbacks for various types of IRP.
// .Create one or more DFWQUEUE request queues.
// Even though we don't want to do anything special with PnP IRPs, the WinHEC 2003
// version of the DFW library requires us to call DfwDeviceRegisterFdoCallbacks, or else
// it crashes when we unload the driver.
DFW_FDO_EVENT_CALLBACKS callbacks;
DFW_FDO_EVENT_CALLBACKS_INIT(&callbacks);
status = DfwDeviceRegisterFdoCallbacks(hDevice, &callbacks);
if (!NT_SUCCESS(status))
{
DfwTraceError(DRIVERNAME " - DfwDeviceRegisterFdoCallbacks failed - %X\n", status);
return status;
}
return status;
} // EvtDriverDeviceAdd
////////////////////////////////////////////////////////////////////////////////
// The framework calls EvtDriverUnload to do any required cleanup of global
// variables in preparation for unloading the driver. This driver has no
// cleanup to perform, so this routine is here just to print a reassuring
// debug message.
#pragma PAGEDCODE
VOID EvtDriverUnload(DFWDRIVER Driver)
{ // EvtDriverUnload
PAGED_CODE();
DfwTraceDbgPrint(DRIVERNAME " - Unloading driver - IRQL is %d\n", KeGetCurrentIrql());
} // EvtDriverUnload
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -