543 lines
11 KiB
C
543 lines
11 KiB
C
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
vfdriver.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the verifier driver filter.
|
|
|
|
Author:
|
|
|
|
Adrian J. Oney (adriao) 12-June-2000
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
AdriaO 06/12/2000 - Authored
|
|
|
|
--*/
|
|
|
|
#include "vfdef.h" // Includes vfdef.h
|
|
#include "vidriver.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGEVRFY, VfDriverInit)
|
|
#pragma alloc_text(PAGEVRFY, VfDriverAttachFilter)
|
|
#pragma alloc_text(PAGEVRFY, ViDriverEntry)
|
|
#pragma alloc_text(PAGEVRFY, ViDriverAddDevice)
|
|
#pragma alloc_text(PAGEVRFY, ViDriverDispatchPnp)
|
|
#pragma alloc_text(PAGEVRFY, ViDriverStartCompletionRoutine)
|
|
#pragma alloc_text(PAGEVRFY, ViDriverDeviceUsageNotificationCompletionRoutine)
|
|
#pragma alloc_text(PAGEVRFY, ViDriverDispatchPower)
|
|
#pragma alloc_text(PAGEVRFY, ViDriverDispatchGeneric)
|
|
#pragma alloc_text(PAGEVRFY, VfDriverIsVerifierFilterObject)
|
|
#endif
|
|
|
|
PDRIVER_OBJECT VfDriverObject = NULL;
|
|
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma const_seg("PAGEVRFC")
|
|
#endif
|
|
|
|
WCHAR VerifierDriverName[] = L"\\DRIVER\\VERIFIER";
|
|
BOOLEAN VfDriverCreated = FALSE;
|
|
|
|
VOID
|
|
VfDriverInit(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the driver verifier filter code.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
VOID
|
|
VfDriverAttachFilter(
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
IN VF_DEVOBJ_TYPE DeviceObjectType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the Verifier driver dispatch handler for PnP IRPs.
|
|
|
|
Arguments:
|
|
|
|
PhysicalDeviceObject - Bottom of stack to attach to.
|
|
|
|
DeviceObjectType - Type of filter the device object must simulate.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PDEVICE_OBJECT newDeviceObject, lowerDeviceObject;
|
|
PVERIFIER_EXTENSION verifierExtension;
|
|
UNICODE_STRING driverString;
|
|
|
|
if (!VfDriverCreated) {
|
|
|
|
RtlInitUnicodeString(&driverString, VerifierDriverName);
|
|
|
|
IoCreateDriver(&driverString, ViDriverEntry);
|
|
|
|
VfDriverCreated = TRUE;
|
|
}
|
|
|
|
if (VfDriverObject == NULL) {
|
|
|
|
return;
|
|
}
|
|
|
|
switch(DeviceObjectType) {
|
|
|
|
case VF_DEVOBJ_PDO:
|
|
//
|
|
// This makes no sense. We can't impersonate a PDO.
|
|
//
|
|
return;
|
|
|
|
case VF_DEVOBJ_BUS_FILTER:
|
|
//
|
|
// We don't have the code to impersonate a bus filter yet.
|
|
//
|
|
return;
|
|
|
|
case VF_DEVOBJ_LOWER_DEVICE_FILTER:
|
|
case VF_DEVOBJ_LOWER_CLASS_FILTER:
|
|
break;
|
|
|
|
case VF_DEVOBJ_FDO:
|
|
//
|
|
// This makes no sense. We can't impersonate an FDO.
|
|
//
|
|
return;
|
|
|
|
case VF_DEVOBJ_UPPER_DEVICE_FILTER:
|
|
case VF_DEVOBJ_UPPER_CLASS_FILTER:
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// We don't even know what this is!
|
|
//
|
|
ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
lowerDeviceObject = IoGetAttachedDevice(PhysicalDeviceObject);
|
|
if (lowerDeviceObject->DriverObject == VfDriverObject) {
|
|
|
|
//
|
|
// No need to add another filter. We are immediately below.
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create a filter device object.
|
|
//
|
|
status = IoCreateDevice(
|
|
VfDriverObject,
|
|
sizeof(VERIFIER_EXTENSION),
|
|
NULL, // No Name
|
|
FILE_DEVICE_UNKNOWN,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
FALSE,
|
|
&newDeviceObject
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
return;
|
|
}
|
|
|
|
verifierExtension = (PVERIFIER_EXTENSION) newDeviceObject->DeviceExtension;
|
|
|
|
verifierExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(
|
|
newDeviceObject,
|
|
PhysicalDeviceObject
|
|
);
|
|
|
|
//
|
|
// Failure for attachment is an indication of a broken plug & play system.
|
|
//
|
|
if (verifierExtension->LowerDeviceObject == NULL) {
|
|
|
|
IoDeleteDevice(newDeviceObject);
|
|
return;
|
|
}
|
|
|
|
newDeviceObject->Flags |= verifierExtension->LowerDeviceObject->Flags &
|
|
(DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH);
|
|
|
|
newDeviceObject->DeviceType = verifierExtension->LowerDeviceObject->DeviceType;
|
|
|
|
newDeviceObject->Characteristics =
|
|
verifierExtension->LowerDeviceObject->Characteristics;
|
|
|
|
verifierExtension->Self = newDeviceObject;
|
|
verifierExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
|
|
|
newDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ViDriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the callback function when we call IoCreateDriver to create a
|
|
Verifier Driver Object. In this function, we need to remember the
|
|
DriverObject.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to the driver object created by the system.
|
|
|
|
RegistryPath - is NULL.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
|
|
UNREFERENCED_PARAMETER(RegistryPath);
|
|
|
|
//
|
|
// File the pointer to our driver object away
|
|
//
|
|
VfDriverObject = DriverObject;
|
|
|
|
//
|
|
// Fill in the driver object
|
|
//
|
|
DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE) ViDriverAddDevice;
|
|
|
|
//
|
|
// Most IRPs are simply pass though
|
|
//
|
|
for(i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
|
|
|
DriverObject->MajorFunction[i] = ViDriverDispatchGeneric;
|
|
}
|
|
|
|
//
|
|
// PnP and Power IRPs are of course trickier.
|
|
//
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = ViDriverDispatchPnp;
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = ViDriverDispatchPower;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ViDriverAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the AddDevice callback function exposed by the verifier driver
|
|
object. It should never be invoked by the operating system.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to the verifier driver object.
|
|
|
|
PhysicalDeviceObject - Stack PnP wishes to attach this driver too.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(DriverObject);
|
|
UNREFERENCED_PARAMETER(PhysicalDeviceObject);
|
|
|
|
//
|
|
// We should never get here!
|
|
//
|
|
ASSERT(0);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ViDriverDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the Verifier driver dispatch handler for PnP IRPs.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the verifier device object.
|
|
|
|
Irp - Pointer to the incoming IRP.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PVERIFIER_EXTENSION verifierExtension;
|
|
PIO_STACK_LOCATION irpSp;
|
|
PDEVICE_OBJECT lowerDeviceObject;
|
|
NTSTATUS status;
|
|
|
|
verifierExtension = (PVERIFIER_EXTENSION) DeviceObject->DeviceExtension;
|
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
lowerDeviceObject = verifierExtension->LowerDeviceObject;
|
|
|
|
switch(irpSp->MinorFunction) {
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
IoSetCompletionRoutine(
|
|
Irp,
|
|
ViDriverStartCompletionRoutine,
|
|
NULL,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE
|
|
);
|
|
|
|
return IoCallDriver(lowerDeviceObject, Irp);
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
status = IoCallDriver(lowerDeviceObject, Irp);
|
|
|
|
IoDetachDevice(lowerDeviceObject);
|
|
IoDeleteDevice(DeviceObject);
|
|
return status;
|
|
|
|
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
|
|
|
|
//
|
|
// On the way down, pagable might become set. Mimic the driver
|
|
// above us. If no one is above us, just set pagable.
|
|
//
|
|
if ((DeviceObject->AttachedDevice == NULL) ||
|
|
(DeviceObject->AttachedDevice->Flags & DO_POWER_PAGABLE)) {
|
|
|
|
DeviceObject->Flags |= DO_POWER_PAGABLE;
|
|
}
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
IoSetCompletionRoutine(
|
|
Irp,
|
|
ViDriverDeviceUsageNotificationCompletionRoutine,
|
|
NULL,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE
|
|
);
|
|
|
|
return IoCallDriver(lowerDeviceObject, Irp);
|
|
}
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
return IoCallDriver(lowerDeviceObject, Irp);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ViDriverStartCompletionRoutine(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
PVERIFIER_EXTENSION verifierExtension;
|
|
|
|
UNREFERENCED_PARAMETER(Context);
|
|
|
|
if (Irp->PendingReturned) {
|
|
|
|
IoMarkIrpPending(Irp);
|
|
}
|
|
|
|
verifierExtension = (PVERIFIER_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// Inherit FILE_REMOVABLE_MEDIA during Start. This characteristic didn't
|
|
// make a clean transition from NT4 to NT5 because it wasn't available
|
|
// until the driver stack is started! Even worse, drivers *examine* this
|
|
// characteristic during start as well.
|
|
//
|
|
if (verifierExtension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
|
|
|
|
DeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ViDriverDeviceUsageNotificationCompletionRoutine(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
PVERIFIER_EXTENSION verifierExtension;
|
|
|
|
UNREFERENCED_PARAMETER(Context);
|
|
|
|
if (Irp->PendingReturned) {
|
|
|
|
IoMarkIrpPending(Irp);
|
|
}
|
|
|
|
verifierExtension = (PVERIFIER_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
//
|
|
// On the way up, pagable might become clear. Mimic the driver below us.
|
|
//
|
|
if (!(verifierExtension->LowerDeviceObject->Flags & DO_POWER_PAGABLE)) {
|
|
|
|
DeviceObject->Flags &= ~DO_POWER_PAGABLE;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ViDriverDispatchPower(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the Verifier driver dispatch handler for Power IRPs.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the verifier device object.
|
|
|
|
Irp - Pointer to the incoming IRP.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PVERIFIER_EXTENSION verifierExtension;
|
|
|
|
verifierExtension = (PVERIFIER_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
return PoCallDriver(verifierExtension->LowerDeviceObject, Irp);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ViDriverDispatchGeneric(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the Verifier driver dispatch handler for generic IRPs.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the verifier device object.
|
|
|
|
Irp - Pointer to the incoming IRP.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PVERIFIER_EXTENSION verifierExtension;
|
|
|
|
verifierExtension = (PVERIFIER_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
return IoCallDriver(verifierExtension->LowerDeviceObject, Irp);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
VfDriverIsVerifierFilterObject(
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This determines whether the passed in device object is a verifier DO.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object to check.
|
|
|
|
Return Value:
|
|
|
|
TRUE/FALSE
|
|
|
|
--*/
|
|
{
|
|
return (BOOLEAN) (DeviceObject->DriverObject->MajorFunction[IRP_MJ_PNP] == ViDriverDispatchPnp);
|
|
}
|
|
|