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

📄 driverentry.cpp

📁 一本在讲述USB驱动程式的书 及其范例原码
💻 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 + -