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

📄 control.cpp

📁 Programming the Microsoft Windows driver model.2nd 随书光盘。内有很多作者送的实用工具和随书源码。WDM编程
💻 CPP
字号:
// Control.cpp -- IOCTL handlers for hidfake driver

// Copyright (C) 1999, 2000 by Walter Oney

// All rights reserved



#include "stddcls.h"

#include "driver.h"

#include "version.h"

#include "FeatureReports.h"



// The faux HID descriptor we use originates in DT.EXE (The HID descriptor

// tool from usb.org), which saves the header file we use here. Note that

// ReportDescriptor.hid, the internal representation of the descriptor, is

// part of the project but doesn't participate directly in the build.



unsigned						// mates with "char" at start of the following...

#include "ReportDescriptor.h"	// generated by dt.exe from ReportDescriptor.hid



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

// The DispatchInternalControl callback for a HID minidriver is the primary 

// way we have of communicating with the outside world.



#pragma LOCKEDCODE



NTSTATUS DispatchInternalControl(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchInternalControl

	PDEVICE_EXTENSION pdx = PDX(fdo);

	NTSTATUS status = STATUS_SUCCESS;

	ULONG info = 0;



	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

	ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;

	ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;

	ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;

	PVOID buffer = Irp->UserBuffer;	// most codes use METHOD_NEITHER



	switch (code)

		{						// process HIDCLASS request



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

	// IOCTL_HID_GET_DEVICE_DESCRIPTOR gets descriptor information about the

	// device. With a USB device, this would be the standard HID class descriptor.



	case IOCTL_HID_GET_DEVICE_DESCRIPTOR:

		{						// IOCTL_HID_GET_DEVICE_DESCRIPTOR

		KdPrint((DRIVERNAME " - IOCTL_HID_GET_DEVICE_DESCRIPTOR\n"));

		#define p ((PHID_DESCRIPTOR) buffer)

		if (cbout < sizeof(HID_DESCRIPTOR))

			{

			status = STATUS_BUFFER_TOO_SMALL;

			break;

			}



		// Construct a dummy HID descriptor as from a USB device



		RtlZeroMemory(p, sizeof(HID_DESCRIPTOR));

		p->bLength = sizeof(HID_DESCRIPTOR);

		p->bDescriptorType = HID_HID_DESCRIPTOR_TYPE;

		p->bcdHID = HID_REVISION;

		p->bCountry = 0;		// not localized

		p->bNumDescriptors = 1;	// 1 report descriptor, no physical descriptor



		p->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE;

		p->DescriptorList[0].wReportLength = sizeof(ReportDescriptor);



		#undef p



		info = sizeof(HID_DESCRIPTOR);

		break;

		}						// IOCTL_HID_GET_DEVICE_DESCRIPTOR



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

	// IOCTL_HID_GET_REPORT_DESCRIPTOR gets the report descriptor for the device.

	// With a USB device, this would be the standard report descriptor.



	case IOCTL_HID_GET_REPORT_DESCRIPTOR:

		{						// IOCTL_HID_GET_REPORT_DESCRIPTOR

		KdPrint((DRIVERNAME " - IOCTL_HID_GET_REPORT_DESCRIPTOR\n"));

		if (cbout < sizeof(ReportDescriptor))

			{

			status = STATUS_BUFFER_TOO_SMALL;

			break;

			}



		RtlCopyMemory(buffer, ReportDescriptor, sizeof(ReportDescriptor));

		info = sizeof(ReportDescriptor);



		break;

		}						// IOCTL_HID_GET_REPORT_DESCRIPTOR



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

	// IOCTL_HID_GET_DEVICE_ATTRIBUTES gets information about the device as a

	// whole. With a USB device, this would come from the USB standard device

	// descriptor.



	case IOCTL_HID_GET_DEVICE_ATTRIBUTES:

		{						// IOCTL_HID_GET_DEVICE_ATTRIBUTES

		KdPrint((DRIVERNAME " - IOCTL_HID_GET_DEVICE_ATTRIBUTES\n"));

		if (cbout < sizeof(HID_DEVICE_ATTRIBUTES))

			{

			status = STATUS_BUFFER_TOO_SMALL;

			break;

			}



		#define p ((PHID_DEVICE_ATTRIBUTES) buffer)



		// Note: a joystick needs unique vendor and product ids, which must dovetail

		// with the subkey name used in the OEM registry. We use dummy values here to

		// make it easy for the test applet to find the right collection object.



		RtlZeroMemory(p, sizeof(HID_DEVICE_ATTRIBUTES));

		p->Size = sizeof(HID_DEVICE_ATTRIBUTES);

		p->VendorID = HIDFAKE_VID;

		p->ProductID = HIDFAKE_PID;

		p->VersionNumber = 1;



		#undef p



		info = sizeof(HID_DEVICE_ATTRIBUTES);

		break;

		}						// IOCTL_HID_GET_DEVICE_ATTRIBUTES



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

	// IOCTL_HID_READ_REPORT retrieves a single report from the device. There will

	// be great variability in how you implement this function, depending on many

	// factors that are too numerous to elaborate in code. This device has a dummy

	// button whose state is continuously reflected in the ButtonDown flag in the

	// the device extension.



	case IOCTL_HID_READ_REPORT:

		{						// IOCTL_HID_READ_REPORT

		KdPrint((DRIVERNAME " - IOCTL_HID_READ_REPORT\n"));

		if (cbout < sizeof(BUTTON_REPORT))

			{

			status = STATUS_BUFFER_TOO_SMALL;

			break;

			}



		// Fill in the report. Note that, since this device has numbered feature

		// reports, the HID parser insists that the regular input report have

		// an id as well. If you're writing a driver that uses feature reports

		// solely for application interfacing, you would need to *add* a report id

		// to each input report from the real device. Bit of a pain, actually...



		#define p ((PBUTTON_REPORT) buffer)

		p->id = 1;

		p->Buttons = pdx->ButtonDown;

		#undef p



		info = sizeof(BUTTON_REPORT);

		break;

		}						// IOCTL_HID_READ_REPORT



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

	// IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST asks us to callback to HIDCLASS

	// when it is possible or sensible to power down the device. A non-standard

	// USB device should forward this IRP down the stack as a regular

	// IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION. A non-USB device should

	// do what this sample does, namely callback immediately to allow HIDCLASS

	// to depower the device.



	case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:

		{						// IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST

		KdPrint((DRIVERNAME " - IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST\n"));

		PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO p = (PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO)

			stack->Parameters.DeviceIoControl.Type3InputBuffer;

		(*p->IdleCallback)(p->IdleContext);

		break;

		}						// IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST



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

	// The foregoing are the only IOCTLs that you have to support in a minimal minidriver.

	// We also support the following two, which is how the test applet communicates with

	// us "out of band"



	case IOCTL_HID_GET_FEATURE:

		{						// IOCTL_HID_GET_FEATURE

		KdPrint((DRIVERNAME " - IOCTL_HID_GET_FEATURE\n"));

		if (cbout < sizeof(HID_XFER_PACKET))

			{

			status = STATUS_BUFFER_TOO_SMALL;

			break;

			}



		#define p ((PHID_XFER_PACKET) buffer)

		if (p->reportId != FEATURE_CODE_GET_VERSION)

			{

			status = STATUS_NOT_SUPPORTED;

			break;

			}



		// This driver supports a GetFeature request to return the revision level of the

		// driver. Since we are using report ids in our top-level collection, the buffer

		// includes a byte for the id. (If we weren't using report ids, the buffer *we* get

		// doesn't have the id byte even though HIDCLASS's caller's buffer *does*. Something

		// to watch out for...)



		if (p->reportBufferLen < sizeof(FEATURE_REPORT_GET_VERSION))

			{

			status = STATUS_BUFFER_TOO_SMALL;

			break;

			}



		#define q ((PFEATURE_REPORT_GET_VERSION) (p->reportBuffer))

		ASSERT(q->id == FEATURE_CODE_GET_VERSION);

		q->Version = (VERMAJOR << 16) | VERMINOR;



		#undef q

		#undef p



		info = sizeof(FEATURE_REPORT_GET_VERSION);

		break;

		}						// IOCTL_HID_GET_FEATURE



	case IOCTL_HID_SET_FEATURE:

		{						// IOCTL_HID_SET_FEATURE

		KdPrint((DRIVERNAME " - IOCTL_HID_SET_FEATURE\n"));



		// Note that *cbin* should be the size of the xfer packet, even though its address

		// is at Irp->UserBuffer instead of stack->Parameters.DeviceIoControl.Type3InputBuffer.

		// Like the book says, this is a *callback* function rather than a real IRP processor.



		if (cbin < sizeof(HID_XFER_PACKET))

			{

			status = STATUS_BUFFER_TOO_SMALL;

			break;

			}



		#define p ((PHID_XFER_PACKET) buffer)

		if (p->reportId != FEATURE_CODE_SET_BUTTON)

			{

			status = STATUS_NOT_SUPPORTED;

			break;

			}



		// This driver supports a SetFeature request to set the state of the fake

		// button control



		if (p->reportBufferLen < sizeof(FEATURE_REPORT_SET_BUTTON))

			{

			status = STATUS_BUFFER_TOO_SMALL;

			break;

			}



		#define q ((PFEATURE_REPORT_SET_BUTTON) (p->reportBuffer))

		ASSERT(q->id == FEATURE_CODE_SET_BUTTON);

		pdx->ButtonDown = q->ButtonDown;



		KdPrint((DRIVERNAME " - Simulated button is %s\n", pdx->ButtonDown ? "down" : "up"));



		#undef q

		#undef p



		break;

		}						// IOCTL_HID_SET_FEATURE



	default:

		status = STATUS_NOT_SUPPORTED;

		break;

		}						// process HIDCLASS request



	if (status != STATUS_PENDING)

		CompleteRequest(Irp, status, info);

	return status;

	}							// DispatchInternalControl



#pragma LOCKEDCODE				// force inline functions into nonpaged code



⌨️ 快捷键说明

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