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

📄 driverentry.cpp

📁 Programming the Microsoft Windows driver model.2nd 随书光盘。内有很多作者送的实用工具和随书源码。WDM编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Main program for wdmstub driver

// Copyright (C) 2000 by Walter Oney

// All rights reserved



// Use this driver as a lower filter for any WDM driver that uses one or more

// of the non-WDM functions this driver supports.



#include "stddcls.h"

#include "driver.h"

#include "version.h"



NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo);

VOID DriverUnload(IN PDRIVER_OBJECT fdo);

NTSTATUS DispatchAny(IN PDEVICE_OBJECT fido, IN PIRP Irp);

NTSTATUS DispatchInternalControl(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);



BOOLEAN IsWin98();

BOOLEAN StubsDefined = FALSE;	// true if we defined any stubs

PDEVICE_OBJECT DummyDeviceObject = NULL;	// dummy device object

BOOLEAN CheckCloneVersions(PDRIVER_OBJECT DriverObject);



///////////////////////////////////////////////////////////////////////////////

// Declare dummy symbols to bound the pointers emitted by the compiler for

// static initialization functions.



typedef void (__cdecl *INITFUNCTION)();



#pragma data_seg(".CRT$XCA")

static INITFUNCTION BeginInitFunctions[1] = {0};



#pragma data_seg(".CRT$XCZ")

static INITFUNCTION EndInitFunctions[1] = {0};



#pragma data_seg()



///////////////////////////////////////////////////////////////////////////////



#pragma INITCODE



extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,

	IN PUNICODE_STRING RegistryPath)

	{							// DriverEntry



	// See if we're running under Win98 or NT:



	if (!IsWin98())

		{

		KdPrint((DRIVERNAME " - Driver should only be used in Windows 98"));

		return STATUS_UNSUCCESSFUL;

		}



	// Execute static initialization routines. This became necessary with SP-9

	// when we started using the Xp DDK compiler



	for (INITFUNCTION* p = BeginInitFunctions + 1; p < EndInitFunctions; ++p)

		(*p)();



	// 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;

	DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalControl;



	// See if there are other instances of WDMSTUB running on this computer. These

	// might include the original WDMSTUB.VXD from the book or an OEM clone of this

	// driver.



	StubsDefined = CheckCloneVersions(DriverObject);



	// Create export definitions for the WDM functions this driver supplies



	if (StubsDefined && !DefineStubs())

		{						// error defining stubs

		ObDereferenceObject(DriverObject);

		IoDeleteDevice(DummyDeviceObject);

		return STATUS_UNSUCCESSFUL;

		}						// error defining stubs



	return STATUS_SUCCESS;

	}							// DriverEntry



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)

	{							// AddDevice

	PAGED_CODE();



	NTSTATUS status;



	// Create a function device object to represent the hardware we're managing.



	PDEVICE_OBJECT fdo;

	#define xsize sizeof(DEVICE_EXTENSION)

	status = IoCreateDevice(DriverObject, xsize, NULL,

		FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);

	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) fdo->DeviceExtension;



	// From this point forward, any error will have side effects that need to

	// be cleaned up.



	do

		{						// finish initialization

		pdx->DeviceObject = fdo;

		pdx->Pdo = pdo;



		// Add our device object to the stack and propagate critical settings

		// from the immediately lower device object



		PDEVICE_OBJECT ldo = IoAttachDeviceToDeviceStack(fdo, pdo);

		if (!ldo)

			{						// can't attach device

			KdPrint((DRIVERNAME " - IoAttachDeviceToDeviceStack failed\n"));

			status = STATUS_DEVICE_REMOVED;

			break;;

			}						// can't attach device



		pdx->LowerDeviceObject = ldo;

		fdo->DeviceType = ldo->DeviceType;

		fdo->Characteristics = ldo->Characteristics;



		// 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.



		fdo->Flags |= ldo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO);



		// Indicate that we have a pagable power handler. The reason we do this is actually fairly

		// complex, as follows. It's okay to have a pagable power handler layered above a non-paged

		// or in-rush power handler, but not the other way around. If we're an upper filter for any

		// kind of device, it's safer to leave this flag set always. If we were to clear it (for

		// example, because we notice that the guy under us is non-paged or becomes so after

		// processing a usage notification), we would have to always set it when passing down

		// usage notifications later on or risk violating the rule.



		// IF WE ARE A LOWER FILTER FOR A DEVICE THAT HAS A NON-PAGABLE POWER HANDLER, OR FOR A

		// DEVICE THAT CHANGES BETWEEN PAGED AND NON-PAGED DEPENDING ON USAGE NOTIFICATIONS, THIS

		// SIMPLISTIC CODE IS WRONG. YOU MUST FIND OUT HOW THE UPPER DRIVER WILL HANDLE THE

		// DO_POWER_PAGABLE FLAG AND DO THE RIGHT THING.



		fdo->Flags |= DO_POWER_PAGABLE;



		// Clear the "initializing" flag so that we can get IRPs



		fdo->Flags &= ~DO_DEVICE_INITIALIZING;

		}						// finish initialization

	while (FALSE);



	if (!NT_SUCCESS(status))

		{					// need to cleanup

		if (pdx->LowerDeviceObject)

			IoDetachDevice(pdx->LowerDeviceObject);

		IoDeleteDevice(fdo);

		}					// need to cleanup



	return status;

	}							// AddDevice



///////////////////////////////////////////////////////////////////////////////

// CheckCloneVersions looks for the VxD version of WDMSTUB or an OEM clone of

// this same filter driver and evaluates the version number(s) of any such.

// It returns TRUE if version checking indicates that we should stub or implement

// at least one function.



#pragma PAGEDCODE



BOOLEAN CheckCloneVersions(PDRIVER_OBJECT DriverObject)

	{							// CheckCloneVersions

	BOOLEAN result = TRUE;



	// See if there is a VxD version of WDMSTUB loaded and, if so, what it's version

	// number is.



	PVMMDDB ddb = Get_DDB(0, "WDMSTUB ");

	if (ddb)

		{						// VxD version loaded

		if (ddb->DDB_Dev_Major_Version > VERMAJOR || (ddb->DDB_Dev_Major_Version == VERMAJOR && ddb->DDB_Dev_Minor_Version > VERMINOR))

			{					// defer to VxD

			KdPrint((DRIVERNAME " - Deferring to WDMSTUB.VXD version %d.%2.2d\n", ddb->DDB_Dev_Major_Version, ddb->DDB_Dev_Minor_Version));

			result = FALSE;

			}					// defer to VxD

		else

			KdPrint((DRIVERNAME " - Overriding WDMSTUB.VXD version %d.%2.2d\n", ddb->DDB_Dev_Major_Version, ddb->DDB_Dev_Minor_Version));

		}						// VxD version loaded



	// See if there is a clone of this filter driver with a higher version number



	ULONG index;				// current driver index

	ULONG avail = 0xFFFFFFFF;	// an available driver index

	WCHAR namebuf[32];

	UNICODE_STRING devname;



	KEVENT event;

	KeInitializeEvent(&event, SynchronizationEvent, FALSE);

	IO_STATUS_BLOCK iostatus;

	NTSTATUS status;



	// Look for dummy device objects WDMSTUB0 through WDMSTUB99



	for (index = 0; index < 100 && result; ++index)

		{						// for each possible driver index

		_snwprintf(namebuf, arraysize(namebuf), L"\\Device\\WDMSTUB%d", index);

		RtlInitUnicodeString(&devname, namebuf);



		PFILE_OBJECT fop;

		PDEVICE_OBJECT clone;

		status = IoGetDeviceObjectPointer(&devname, FILE_READ_DATA, &fop, &clone);



		// If there is a device object with this name, send it a get-version IOCTL



		if (NT_SUCCESS(status))

			{					// found a clone

			ULONG version;

			PIRP Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_WDMSTUB_GET_VERSION, clone, NULL, 0, &version, sizeof(version),

				TRUE, &event, &iostatus);

			if (!Irp)

				{

				KdPrint((DRIVERNAME " - Unable to allocate IRP for version query\n"));

				result = FALSE;

				}

			else

				{				// send IRP

				status = IoCallDriver(clone, Irp);

				if (status == STATUS_PENDING)

					{			// wait for IRP

					KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);

					status = iostatus.Status;

					}			// wait for IRP

				if (NT_SUCCESS(status))

					{			// check version #

					if (version >= ((VERMAJOR << 16) | VERMINOR))

						{		// found higher version

						KdPrint((DRIVERNAME " - Deferring to WDMSTUB clone version %d.%2.2d\n", version >> 16, version & 0xFFFF));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -