⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driverentry.cpp

📁 Programming the Microsoft Windows Driver Model(2nd)
💻 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 + -