📄 driverentry.cpp
字号:
// Main program for filter driver
// Copyright (C) 1999 by Walter Oney
// All rights reserved
#include "stddcls.h"
#include "driver.h"
NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo);
VOID DriverUnload(IN PDRIVER_OBJECT fido);
NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp);
NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp);
NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp);
NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fido, IN PIRP Irp);
ULONG GetDeviceTypeToUse(PDEVICE_OBJECT pdo);
NTSTATUS StartDeviceCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx);
NTSTATUS UsageNotificationCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx);
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{ // DriverEntry
KdPrint((DRIVERNAME " - Entering DriverEntry: DriverObject %8.8lX\n", DriverObject));
// Initialize function pointers
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = AddDevice;
for (int i = 0; i < arraysize(DriverObject->MajorFunction); ++i)
DriverObject->MajorFunction[i] = DispatchAny;
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
return STATUS_SUCCESS;
} // DriverEntry
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{ // DriverUnload
PAGED_CODE();
KdPrint((DRIVERNAME " - Entering DriverUnload: DriverObject %8.8lX\n", DriverObject));
} // DriverUnload
///////////////////////////////////////////////////////////////////////////////
NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
{ // AddDevice
PAGED_CODE();
KdPrint((DRIVERNAME " - Entering AddDevice: DriverObject %8.8lX, pdo %8.8lX\n", DriverObject, pdo));
NTSTATUS status;
// Create a device object. Do *not* specify any device characteristics here because
// some of them will get applied to all drivers in the stack, and it's not up to
// us as a filter to control any of the propagated attributes (e.g., FILE_DEVICE_SECURE_OPEN).
// The call to GetDeviceTypeToUse was added in SP-9 to overcome a bug in CDFS.
PDEVICE_OBJECT fido;
status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL,
GetDeviceTypeToUse(pdo), 0, FALSE, &fido);
if (!NT_SUCCESS(status))
{ // can't create device object
KdPrint((DRIVERNAME " - IoCreateDevice failed - %X\n", status));
return status;
} // can't create device object
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
// From this point forward, any error will have side effects that need to
// be cleaned up.
do
{ // finish initialization
IoInitializeRemoveLock(&pdx->RemoveLock, 0, 0, 0);
pdx->DeviceObject = fido;
pdx->Pdo = pdo;
// Add our device object to the stack and propagate critical settings
// from the immediately lower device object
PDEVICE_OBJECT fdo = IoAttachDeviceToDeviceStack(fido, pdo);
if (!fdo)
{ // can't attach
KdPrint((DRIVERNAME " - IoAttachDeviceToDeviceStack failed\n"));
status = STATUS_DEVICE_REMOVED;
break;;
} // can't attach
pdx->LowerDeviceObject = fdo;
// Copy the flags related to I/O buffering from the lower device object so the I/O manager
// will create the expected data structures for reads and writes.
fido->Flags |= fdo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE);
// Clear the "initializing" flag so that we can get IRPs
fido->Flags &= ~DO_DEVICE_INITIALIZING;
} // finish initialization
while (FALSE);
if (!NT_SUCCESS(status))
{ // need to cleanup
if (pdx->LowerDeviceObject)
IoDetachDevice(pdx->LowerDeviceObject);
IoDeleteDevice(fido);
} // need to cleanup
return status;
} // AddDevice
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN ULONG_PTR info)
{ // CompleteRequest
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
} // CompleteRequest
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE // make no assumptions about pageability of dispatch fcns
NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{ // DispatchAny
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
#if DBG
static char* irpname[] = {
"IRP_MJ_CREATE",
"IRP_MJ_CREATE_NAMED_PIPE",
"IRP_MJ_CLOSE",
"IRP_MJ_READ",
"IRP_MJ_WRITE",
"IRP_MJ_QUERY_INFORMATION",
"IRP_MJ_SET_INFORMATION",
"IRP_MJ_QUERY_EA",
"IRP_MJ_SET_EA",
"IRP_MJ_FLUSH_BUFFERS",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION",
"IRP_MJ_DIRECTORY_CONTROL",
"IRP_MJ_FILE_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CONTROL",
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
"IRP_MJ_SHUTDOWN",
"IRP_MJ_LOCK_CONTROL",
"IRP_MJ_CLEANUP",
"IRP_MJ_CREATE_MAILSLOT",
"IRP_MJ_QUERY_SECURITY",
"IRP_MJ_SET_SECURITY",
"IRP_MJ_POWER",
"IRP_MJ_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CHANGE",
"IRP_MJ_QUERY_QUOTA",
"IRP_MJ_SET_QUOTA",
"IRP_MJ_PNP",
};
UCHAR type = stack->MajorFunction;
if (type >= arraysize(irpname))
KdPrint((DRIVERNAME " - Unknown IRP, major type %X\n", type));
else
KdPrint((DRIVERNAME " - %s\n", irpname[type]));
#endif
// Pass request down without additional processing
NTSTATUS status;
status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
} // DispatchAny
///////////////////////////////////////////////////////////////////////////////
NTSTATUS DispatchPower(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{ // DispatchPower
#if DBG
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG fcn = stack->MinorFunction;
static char* fcnname[] = {
"IRP_MN_WAIT_WAKE",
"IRP_MN_POWER_SEQUENCE",
"IRP_MN_SET_POWER",
"IRP_MN_QUERY_POWER",
};
if (fcn == IRP_MN_SET_POWER || fcn == IRP_MN_QUERY_POWER)
{
static char* sysstate[] = {
"PowerSystemUnspecified",
"PowerSystemWorking",
"PowerSystemSleeping1",
"PowerSystemSleeping2",
"PowerSystemSleeping3",
"PowerSystemHibernate",
"PowerSystemShutdown",
"PowerSystemMaximum",
};
static char* devstate[] = {
"PowerDeviceUnspecified",
"PowerDeviceD0",
"PowerDeviceD1",
"PowerDeviceD2",
"PowerDeviceD3",
"PowerDeviceMaximum",
};
ULONG context = stack->Parameters.Power.SystemContext;
POWER_STATE_TYPE type = stack->Parameters.Power.Type;
KdPrint((DRIVERNAME " - IRP_MJ_POWER (%s)", fcnname[fcn]));
if (type == SystemPowerState)
KdPrint((", SystemPowerState = %s\n", sysstate[stack->Parameters.Power.State.SystemState]));
else
KdPrint((", DevicePowerState = %s\n", devstate[stack->Parameters.Power.State.DeviceState]));
}
else if (fcn < arraysize(fcnname))
KdPrint((DRIVERNAME " - IRP_MJ_POWER (%s)\n", fcnname[fcn]));
else
KdPrint((DRIVERNAME " - IRP_MJ_POWER (%2.2X)\n", fcn));
#endif // DBG
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
PoStartNextPowerIrp(Irp); // must be done while we own the IRP
NTSTATUS status;
status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);
IoSkipCurrentIrpStackLocation(Irp);
status = PoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
} // DispatchPower
///////////////////////////////////////////////////////////////////////////////
NTSTATUS DispatchPnp(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{ // DispatchPnp
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG fcn = stack->MinorFunction;
NTSTATUS status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);
#if DBG
static char* pnpname[] = {
"IRP_MN_START_DEVICE",
"IRP_MN_QUERY_REMOVE_DEVICE",
"IRP_MN_REMOVE_DEVICE",
"IRP_MN_CANCEL_REMOVE_DEVICE",
"IRP_MN_STOP_DEVICE",
"IRP_MN_QUERY_STOP_DEVICE",
"IRP_MN_CANCEL_STOP_DEVICE",
"IRP_MN_QUERY_DEVICE_RELATIONS",
"IRP_MN_QUERY_INTERFACE",
"IRP_MN_QUERY_CAPABILITIES",
"IRP_MN_QUERY_RESOURCES",
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
"IRP_MN_QUERY_DEVICE_TEXT",
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
"",
"IRP_MN_READ_CONFIG",
"IRP_MN_WRITE_CONFIG",
"IRP_MN_EJECT",
"IRP_MN_SET_LOCK",
"IRP_MN_QUERY_ID",
"IRP_MN_QUERY_PNP_DEVICE_STATE",
"IRP_MN_QUERY_BUS_INFORMATION",
"IRP_MN_DEVICE_USAGE_NOTIFICATION",
"IRP_MN_SURPRISE_REMOVAL",
"IRP_MN_QUERY_LEGACY_BUS_INFORMATION",
};
if (fcn < arraysize(pnpname))
KdPrint((DRIVERNAME " - IRP_MJ_PNP (%s)\n", pnpname[fcn]));
else
KdPrint((DRIVERNAME " - IRP_MJ_PNP (%2.2X)\n", fcn));
#endif // DBG
// Handle usage notification specially in order to track power pageable
// flag correctly. We need to avoid allowing a non-pageable handler to be
// layered on top of a pageable handler.
if (fcn == IRP_MN_DEVICE_USAGE_NOTIFICATION)
{ // usage notification
if (!fido->AttachedDevice || (fido->AttachedDevice->Flags & DO_POWER_PAGABLE))
fido->Flags |= DO_POWER_PAGABLE;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) UsageNotificationCompletionRoutine,
(PVOID) pdx, TRUE, TRUE, TRUE);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
} // usage notification
// Handle start device specially in order to correctly inherit
// FILE_REMOVABLE_MEDIA
if (fcn == IRP_MN_START_DEVICE)
{ // device start
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) StartDeviceCompletionRoutine,
(PVOID) pdx, TRUE, TRUE, TRUE);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
} // device start
// Handle remove device specially in order to cleanup device stack
if (fcn == IRP_MN_REMOVE_DEVICE)
{ // remove device
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
RemoveDevice(fido);
return status;
} // remove device
// Simply forward any other type of PnP request
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
} // DispatchPnp
///////////////////////////////////////////////////////////////////////////////
// GetDeviceTypeToUse returns the device object type of the next lower device
// object. This helps overcome a bug in some Win2K file systems which expect the
// topmost FiDO in a storage stack to have a VPB and, hence, to have been created
// with a type such as FILE_DEVICE_DISK.
#pragma PAGEDCODE
ULONG GetDeviceTypeToUse(PDEVICE_OBJECT pdo)
{ // GetDeviceTypeToUse
PDEVICE_OBJECT ldo = IoGetAttachedDeviceReference(pdo);
if (!ldo)
return FILE_DEVICE_UNKNOWN;
ULONG devtype = ldo->DeviceType;
ObDereferenceObject(ldo);
return devtype;
} // GetDeviceTypeToUse
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
VOID RemoveDevice(IN PDEVICE_OBJECT fido)
{ // RemoveDevice
PAGED_CODE();
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
NTSTATUS status;
if (pdx->LowerDeviceObject)
IoDetachDevice(pdx->LowerDeviceObject);
IoDeleteDevice(fido);
} // RemoveDevice
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
NTSTATUS StartDeviceCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx)
{ // StartDeviceCompletionRoutine
if (Irp->PendingReturned)
IoMarkIrpPending(Irp);
// Inherit FILE_REMOVABLE_MEDIA flag from lower object. This is necessary
// for a disk filter, but it isn't available until start-device time. Drivers
// above us may examine the flag as part of their own start-device processing, too.
if (pdx->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
fido->Characteristics |= FILE_REMOVABLE_MEDIA;
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return STATUS_SUCCESS;
} // StartDeviceCompletionRoutine
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
NTSTATUS UsageNotificationCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx)
{ // UsageNotificationCompletionRoutine
if (Irp->PendingReturned)
IoMarkIrpPending(Irp);
// If lower driver cleared pageable flag, we must do the same
if (!(pdx->LowerDeviceObject->Flags & DO_POWER_PAGABLE))
fido->Flags &= ~DO_POWER_PAGABLE;
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return STATUS_SUCCESS;
} // UsageNotificationCompletionRoutine
#pragma LOCKEDCODE // force inline functions into nonpaged code
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -