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

📄 control.cpp

📁 一本在讲述USB驱动程式的书 及其范例原码
💻 CPP
字号:
// Control.cpp -- IOCTL handlers for evwait driver
// Copyright (C) 1999 by Walter Oney
// All rights reserved

#include "stddcls.h"
#include "driver.h"
#include "ioctls.h"

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

#pragma LOCKEDCODE				// locked because uses a spin lock

NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)
	{							// DispatchControl
	PAGED_CODE();
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	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;

	switch (code)
		{						// process request

	///////////////////////////////////////////////////////////////////////////
	// IOCTL_REGISTER_EVENT registers or deregisters an event object that the
	// driver shares with a user-mode application.

	case IOCTL_REGISTER_EVENT:				// code == 0x800
		{						// IOCTL_REGISTER_EVENT
		if (cbin < sizeof(HANDLE))
			{
			status = STATUS_INVALID_PARAMETER;
			break;
			}

		// If a new event is being registered, get a pointer to the underlying
		// KEVENT object. This must be done at PASSIVE_LEVEL. This function call is
		// really the main thing this sample illustrates, by the way. Note that the
		// only access we require to the event is EVENT_MODIFY_STATE, so that's all
		// we insist be present for this handle.

		HANDLE hevent = *(PHANDLE) Irp->AssociatedIrp.SystemBuffer;
		PKEVENT pevent;
		if (hevent)
			status = ObReferenceObjectByHandle(hevent, EVENT_MODIFY_STATE, *ExEventObjectType,
				Irp->RequestorMode, (PVOID*) &pevent, NULL);
		else
			pevent = NULL;

		if (!NT_SUCCESS(status))
			break;				// punt -- there's a problem with the handle

		// This driver only allows one handle to be open at a time, so we don't
		// need to worry about where to store the event pointers registered by
		// multiple applications. If you wanted to allow multiple opens and to
		// allow each handle owner to have its own event, you could use
		// stack->FileObject->FsContext or FsContext2 for that purpose, for example.
		//
		// Even though there can be just one handle, an application could use overlapped
		// I/O operations to issue several conflicting calls simultaneously. Hence the
		// use of a synchronization object to guard access to the "event" pointer. In
		// this particular driver, all access to the event pointer occurs at PASSIVE_LEVEL
		// and we could therefore use, e.g., a fast mutex. In general, though, you're going
		// to want to set the event from DISPATCH_LEVEL code. To make your life easier
		// if you're just cutting and pasting code, I therefore used a spin lock. Note
		// that this routine therefore has to be in the locked code segment.

		KIRQL oldirql;
		KeAcquireSpinLock(&pdx->eventlock, &oldirql);

		// First deregister any old event. Then remember the one we just located
		// or NULL.

		if (pdx->event)
			ObDereferenceObject(pdx->event);	// safe to call at <= DISPATCH_LEVEL
		pdx->event = pevent;

		// Now release the synchronization

		KeReleaseSpinLock(&pdx->eventlock, oldirql);
		break;
		}						// IOCTL_REGISTER_EVENT

	///////////////////////////////////////////////////////////////////////////
	// IOCTL_SIGNAL_EVENT event signals the shared event. This particular IOCTL
	// is a hack so you can have a way to test the registration aspect of this sample.
	// In a real situation, there would be some hardware event that would trigger
	// the signalling operation.

	case IOCTL_SIGNAL_EVENT:				// code == 0x801
		{						// IOCTL_SIGNAL_EVENT

		// Synchronize access to the event pointer. In particular, we need to worry about
		// someone coming along and dereferencing the event pointer while we're doing
		// our thing here. You would need synchronization like this in a real driver,
		// where a hardware event triggers the signalling.

		KIRQL oldirql;
		KeAcquireSpinLock(&pdx->eventlock, &oldirql);

		if (pdx->event)
			KeSetEvent(pdx->event, EVENT_INCREMENT, FALSE);

		KeReleaseSpinLock(&pdx->eventlock, oldirql);

		break;
		}						// IOCTL_SIGNAL_EVENT

	default:
		status = STATUS_INVALID_DEVICE_REQUEST;
		break;

		}						// process request

	return CompleteRequest(Irp, status, info);
	}							// DispatchControl

⌨️ 快捷键说明

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