📄 driver.cpp
字号:
//
// Driver.c - HiFilter Driver
// Modifies behavior of LODriver to allow for unlimited
// Write transfer sizes.
//
// Copyright (C) 2000 by Jerry Lozano
//
#include "Driver.h"
// Forward declarations
//
NTSTATUS AddDevice (
IN PDRIVER_OBJECT pDriverObject,
IN PDEVICE_OBJECT pdo );
NTSTATUS DispPnp( IN PDEVICE_OBJECT pDO,
IN PIRP pIrp );
NTSTATUS PassDownPnP( IN PDEVICE_OBJECT pDO,
IN PIRP pIrp );
NTSTATUS HandleStartDevice( IN PDEVICE_OBJECT pDO,
IN PIRP pIrp );
NTSTATUS HandleStopDevice( IN PDEVICE_OBJECT pDO,
IN PIRP pIrp );
NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT pDO,
IN PIRP pIrp );
VOID GetBufferLimits(
IN PDEVICE_OBJECT pTargetDevObj,
OUT PBUFFER_SIZE_INFO pBufferInfo );
static VOID DriverUnload (
IN PDRIVER_OBJECT pDriverObject );
static NTSTATUS OverriddenDispatchWrite (
IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp );
static NTSTATUS OverriddenDispatchIoControl (
IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp );
static NTSTATUS DispatchPassThru (
IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp );
NTSTATUS GenericCompletion(
IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp,
IN PVOID pContext );
NTSTATUS WriteCompletion(
IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp,
IN PVOID pContext );
//++
// Function: DriverEntry
//
// Description:
// Initializes the driver.
//
// Arguments:
// pDriverObject - Passed from I/O Manager
// pRegistryPath - UNICODE_STRING pointer to
// registry info (service key)
// for this driver
//
// Return value:
// NTSTATUS signaling success or failure
//--
extern "C" NTSTATUS DriverEntry (
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath ) {
#if DBG>=1
DbgPrint("HIFILTER: DriverEntry\n");
#endif
ULONG ulDeviceNumber = 0;
NTSTATUS status = STATUS_SUCCESS;
// Assume (initially) nothing is overridden
for (int i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
if (i!=IRP_MJ_POWER)
pDriverObject->MajorFunction[i] = DispatchPassThru;
// Announce other driver entry points
pDriverObject->DriverUnload = DriverUnload;
// Initialize Event logging
InitializeEventLog(pDriverObject);
// Announce the PNP AddDevice entry point
pDriverObject->DriverExtension->AddDevice =
AddDevice;
// Announce the PNP Major Function entry point
pDriverObject->MajorFunction[IRP_MJ_PNP] =
DispPnp;
// Export the overridden MajorFunctions
pDriverObject->MajorFunction[ IRP_MJ_WRITE ] =
OverriddenDispatchWrite;
pDriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] =
OverriddenDispatchIoControl;
// Notice that no device objects are created by DriverEntry.
// Instead, we await the PnP call to AddDevice
return status;
}
//++
// Function: AddDevice
//
// Description:
// Called by the PNP Manager when a new device is
// detected on a bus. The responsibilities include
// creating an FDO, and duplicating the lower device's
// characteristics.
//
// Arguments:
// pDriverObject - Passed from PNP Manager
// pdo - pointer to Physcial Device Object
// passed from PNP Manager
//
// Return value:
// NTSTATUS signaling success or failure
//--
NTSTATUS AddDevice (
IN PDRIVER_OBJECT pDriverObject,
IN PDEVICE_OBJECT pdo ) {
NTSTATUS status;
PDEVICE_OBJECT pFilterDevObj;
PDEVICE_EXTENSION pDevExt;
#if DBG>=1
DbgPrint("HIFILTER: AddDevice\n");
#endif
// Create the un-named filter device
status =
IoCreateDevice( pDriverObject,
sizeof(DEVICE_EXTENSION),
NULL, // no name
FILE_DEVICE_UNKNOWN,
0, TRUE,
&pFilterDevObj );
if (!NT_SUCCESS(status))
return status;
// Initialize the Device Extension
pDevExt = (PDEVICE_EXTENSION)pFilterDevObj->DeviceExtension;
pDevExt->pDevice = pFilterDevObj; // back pointer
pDevExt->state = Stopped;
// Pile this new filter on top of the existing target
pDevExt->pTargetDevice = // downward pointer
IoAttachDeviceToDeviceStack( pFilterDevObj, pdo);
// Copy the characteristics of the target into the
// the new filter device object
pFilterDevObj->DeviceType =
pDevExt->pTargetDevice->DeviceType;
pFilterDevObj->Characteristics =
pDevExt->pTargetDevice->Characteristics;
pFilterDevObj->Flags |=
( pDevExt->pTargetDevice->Flags &
( DO_BUFFERED_IO | DO_DIRECT_IO |
DO_POWER_INRUSH | DO_POWER_PAGABLE));
// Initialize Event Logging counters:
pDevExt->IrpRetryCount = 0;
pDevExt->IrpSequenceNumber = 0;
// Explore the limitations of the target device's
// buffer. Save the results in the bufferInfo struct
GetBufferLimits( pDevExt->pTargetDevice,
&pDevExt->bufferInfo );
// Clear the Device Initializing bit since the FDO was created
// outside of DriverEntry.
pFilterDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
// Made it
return STATUS_SUCCESS;
}
VOID GetBufferLimits(
IN PDEVICE_OBJECT pTargetDevObj,
OUT PBUFFER_SIZE_INFO pBufferInfo ) {
KEVENT keIoctlComplete;
IO_STATUS_BLOCK Iosb;
PIRP pIrp;
#if DBG>=1
DbgPrint("HIFILTER: GetBufferLimits\n");
#endif
// Initialize the event that is signaled when the
// IOCTL IRP completes (by the target device)
KeInitializeEvent(
&keIoctlComplete,
NotificationEvent,
FALSE );
// Construct the IRP for the private IOCTL request
pIrp = IoBuildDeviceIoControlRequest(
IOCTL_GET_MAX_BUFFER_SIZE,
pTargetDevObj,
NULL,
0,
pBufferInfo,
sizeof(BUFFER_SIZE_INFO),
FALSE,
&keIoctlComplete,
&Iosb );
// Send the new IRP down to the target
IoCallDriver( pTargetDevObj, pIrp );
// Wait for the target to complete the IRP
LARGE_INTEGER maxWait;
maxWait.QuadPart = -3 * 10000000;
KeWaitForSingleObject(
&keIoctlComplete,
Executive,
KernelMode,
FALSE,
&maxWait ); // wait no more than 3 secs
#if DBG>=1
DbgPrint("HIFILTER: GetBufferLimits: MW=%d, MR=%d\n",
pBufferInfo->MaxWriteLength,
pBufferInfo->MaxReadLength);
#endif
}
NTSTATUS DispatchPassThru(
IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp ) {
PDEVICE_EXTENSION pFilterExt = (PDEVICE_EXTENSION)
pDevObj->DeviceExtension;
PIO_STACK_LOCATION pIrpStack =
IoGetCurrentIrpStackLocation( pIrp );
PIO_STACK_LOCATION pNextIrpStack =
IoGetNextIrpStackLocation( pIrp );
#if DBG>=1
DbgPrint("HIFILTER: DispatchPassThru\n");
#endif
// Copy args to the next level
// IoCopyCurrentIrpStackLocationToNext(pIrp);
*pNextIrpStack = *pIrpStack;
// Set up a completion routine to handle the bubbling
// of the "pending" mark of an IRP
IoSetCompletionRoutine(
pIrp,
GenericCompletion,
NULL,
TRUE, TRUE, TRUE );
// Pass the IRP to the target.
return IoCallDriver(
pFilterExt->pTargetDevice,
pIrp );
}
NTSTATUS GenericCompletion(
IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp,
IN PVOID pContext ) {
if ( pIrp->PendingReturned )
IoMarkIrpPending( pIrp );
return STATUS_SUCCESS;
}
NTSTATUS DispPnp( IN PDEVICE_OBJECT pDO,
IN PIRP pIrp ) {
// obtain current IRP stack location
PIO_STACK_LOCATION pIrpStack;
pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
#if DBG>=1
DbgPrint("HIFILTER: Received PNP IRP: %d\n",
pIrpStack->MinorFunction);
#endif
switch (pIrpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
return HandleStartDevice(pDO, pIrp );
case IRP_MN_STOP_DEVICE:
return HandleStopDevice( pDO, pIrp );
case IRP_MN_REMOVE_DEVICE:
return HandleRemoveDevice( pDO, pIrp );
default:
// if not supported here, just pass it down
return PassDownPnP(pDO, pIrp);
}
// all paths from the switch statement will "return"
// the results of the handler invoked
}
NTSTATUS PassDownPnP( IN PDEVICE_OBJECT pDO,
IN PIRP pIrp ) {
IoSkipCurrentIrpStackLocation( pIrp );
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDO->DeviceExtension;
return IoCallDriver(pDevExt->pTargetDevice, pIrp);
}
NTSTATUS HandleStartDevice( IN PDEVICE_OBJECT pDO,
IN PIRP pIrp ) {
// The stack location contains the Parameter info
PIO_STACK_LOCATION pIrpStack =
IoGetCurrentIrpStackLocation( pIrp );
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDO->DeviceExtension;
#if DBG>=1
DbgPrint("HIFILTER: StartDevice\n");
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -