📄 filter.c
字号:
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
filter.c
Abstract: NULL filter driver -- boilerplate code
Author:
ervinp
Environment:
Kernel mode
Revision History:
--*/
#include <WDM.H>
#include "filter.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, VA_AddDevice)
#pragma alloc_text(PAGE, VA_DriverUnload)
#endif
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Installable driver initialization entry point.
This entry point is called directly by the I/O system.
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to a unicode string representing the path,
to driver-specific key in the registry.
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
ULONG i;
PAGED_CODE();
UNREFERENCED_PARAMETER(RegistryPath);
DBGOUT(("DriverEntry"));
/*
* Route all IRPs on device objects created by this driver
* to our IRP dispatch routine.
*/
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++){
DriverObject->MajorFunction[i] = VA_Dispatch;
}
DriverObject->DriverExtension->AddDevice = VA_AddDevice;
DriverObject->DriverUnload = VA_DriverUnload;
//
// Remember registry path since it is needed for WMI registration
FilterRegistryPath.Length = 0;
FilterRegistryPath.MaximumLength = RegistryPath->Length;
FilterRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
RegistryPath->Length+2,
FILTER_TAG);
RtlCopyUnicodeString(&FilterRegistryPath, RegistryPath);
return STATUS_SUCCESS;
}
NTSTATUS VA_AddDevice(
IN PDRIVER_OBJECT driverObj,
IN PDEVICE_OBJECT physicalDevObj
)
/*++
Routine Description:
The PlugPlay subsystem is handing us a brand new
PDO (Physical Device Object), for which we
(by means of INF registration) have been asked to filter.
We need to determine if we should attach or not.
Create a filter device object to attach to the stack
Initialize that device object
Return status success.
Remember: we can NOT actually send ANY non pnp IRPS to the given driver
stack, UNTIL we have received an IRP_MN_START_DEVICE.
Arguments:
driverObj - pointer to a device object.
physicalDevObj - pointer to a physical device object pointer
created by the underlying bus driver.
Return Value:
NT status code.
--*/
{
NTSTATUS status;
PDEVICE_OBJECT filterDevObj = NULL;
PAGED_CODE();
DBGOUT(("VA_AddDevice: drvObj=%ph, pdo=%ph", driverObj, physicalDevObj));
status = IoCreateDevice( driverObj,
sizeof(struct DEVICE_EXTENSION),
NULL, // name for this device
FILE_DEVICE_UNKNOWN,
FILE_AUTOGENERATED_DEVICE_NAME, // device characteristics
FALSE, // not exclusive
&filterDevObj); // our device object
if (NT_SUCCESS(status)){
struct DEVICE_EXTENSION *devExt;
ASSERT(filterDevObj);
/*
* Initialize device extension for new device object
*/
devExt = (struct DEVICE_EXTENSION *)filterDevObj->DeviceExtension;
RtlZeroMemory(devExt, sizeof(struct DEVICE_EXTENSION));
devExt->signature = DEVICE_EXTENSION_SIGNATURE;
devExt->state = STATE_INITIALIZED;
devExt->filterDevObj = filterDevObj;
devExt->physicalDevObj = physicalDevObj;
devExt->pendingActionCount = 0;
KeInitializeEvent(&devExt->removeEvent, NotificationEvent, FALSE);
/*
* Clear the initializing bit from the new device object's flags.
*/
filterDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
/*
* The DO_POWER_PAGABLE bit of a device object
* indicates to the kernel that the power-handling
* code of the corresponding driver is pageable, and
* so must be called at IRQL 0.
* As a filter driver, we do not want to change the power
* behavior of the driver stack in any way; therefore,
* we copy this bit from the lower device object.
*/
ASSERT(!(filterDevObj->Flags & DO_POWER_PAGABLE));
filterDevObj->Flags |= (physicalDevObj->Flags & DO_POWER_PAGABLE);
/*
* Attach the new device object to the top of the device stack.
*/
devExt->topDevObj = IoAttachDeviceToDeviceStack(filterDevObj, physicalDevObj);
ASSERT(devExt->topDevObj);
DBGOUT(("created filterDevObj %ph attached to %ph.", filterDevObj, devExt->topDevObj));
/*
* This is a do-nothing call to a sample function which
* demonstrates how to read the device's registry area.
* Note that you cannot make this call on devExt->filterDevObj
* because a filter device object does not have a devNode.
* We pass devExt->physicalDevObj, which is the device object
* for which this driver is a filter driver.
*/
RegistryAccessSample(devExt->physicalDevObj);
/*
* WMI specific initialization
*/
FilterInitializeWmiDataBlocks(devExt);
}
ASSERT(NT_SUCCESS(status));
return status;
}
VOID VA_DriverUnload(IN PDRIVER_OBJECT DriverObject)
/*++
Routine Description:
Free all the allocated resources, etc.
Note: Although the DriverUnload function often does nothing,
the driver must set a DriverUnload function in
DriverEntry; otherwise, the kernel will never unload
the driver.
Arguments:
DriverObject - pointer to a driver object.
Return Value:
VOID.
--*/
{
PAGED_CODE();
DBGOUT(("VA_DriverUnload"));
//
// Free memory used by registry path
ExFreePool(FilterRegistryPath.Buffer);
}
NTSTATUS VA_Dispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
/*++
Routine Description:
Common entrypoint for all Io Request Packets
Arguments:
DeviceObject - pointer to a device object.
Irp - Io Request Packet
Return Value:
NT status code.
--*/
{
struct DEVICE_EXTENSION *devExt;
PIO_STACK_LOCATION irpSp;
BOOLEAN passIrpDown = TRUE;
UCHAR majorFunc, minorFunc;
NTSTATUS status;
devExt = DeviceObject->DeviceExtension;
ASSERT(devExt->signature == DEVICE_EXTENSION_SIGNATURE);
InterlockedIncrement(&devExt->TotalIrpCount);
irpSp = IoGetCurrentIrpStackLocation(Irp);
/*
* Get major/minor function codes in private variables
* so we can access them after the IRP is completed.
*/
majorFunc = irpSp->MajorFunction;
minorFunc = irpSp->MinorFunction;
DBGOUT(("VA_Dispatch: majorFunc=%d, minorFunc=%d",
(ULONG)majorFunc, (ULONG)minorFunc));
/*
* For all IRPs except REMOVE, we increment the PendingActionCount
* across the dispatch routine in order to prevent a race condition with
* the REMOVE_DEVICE IRP (without this increment, if REMOVE_DEVICE
* preempted another IRP, device object and extension might get
* freed while the second thread was still using it).
*/
if (!((majorFunc == IRP_MJ_PNP) && (minorFunc == IRP_MN_REMOVE_DEVICE))){
IncrementPendingActionCount(devExt);
}
if ((majorFunc != IRP_MJ_PNP) &&
(majorFunc != IRP_MJ_CLOSE) &&
((devExt->state == STATE_REMOVING) ||
(devExt->state == STATE_REMOVED))){
/*
* While the device is being removed,
* we only pass down the PNP and CLOSE IRPs.
* We fail all other IRPs.
*/
status = Irp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
passIrpDown = FALSE;
}
else {
switch (majorFunc){
case IRP_MJ_PNP:
status = VA_PnP(devExt, Irp);
passIrpDown = FALSE;
break;
case IRP_MJ_POWER:
status = VA_Power(devExt, Irp);
passIrpDown = FALSE;
break;
case IRP_MJ_SYSTEM_CONTROL:
status = VA_SystemControl(devExt, Irp, &passIrpDown);
break;
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
case IRP_MJ_DEVICE_CONTROL:
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
default:
/*
* For unsupported IRPs, we simply send the IRP
* down the driver stack.
*/
break;
}
}
if (passIrpDown){
IoCopyCurrentIrpStackLocationToNext(Irp);
status = IoCallDriver(devExt->topDevObj, Irp);
}
/*
* Balance the increment to PendingActionCount above.
*/
if (!((majorFunc == IRP_MJ_PNP) && (minorFunc == IRP_MN_REMOVE_DEVICE))){
DecrementPendingActionCount(devExt);
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -