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

📄 control.cpp

📁 Programming the Microsoft Windows Driver Model(2nd)
💻 CPP
字号:
// Control.cpp -- IOCTL handlers for workitem driver

// Copyright (C) 1999 by Walter Oney

// All rights reserved



#include "stddcls.h"

#include "driver.h"

#include "ioctls.h"



struct _RANDOM_JUNK

	{

	PDEVICE_EXTENSION DeviceExtension;

	ULONG value;

	PIRP nfyirp;

	PIO_WORKITEM item;

	};

typedef _RANDOM_JUNK RANDOM_JUNK, *PRANDOM_JUNK;



VOID WorkItemCallback(PDEVICE_OBJECT fdo, PRANDOM_JUNK item);



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



#pragma PAGEDCODE



NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchControl

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;



	NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);

	if (!NT_SUCCESS(status))

		return CompleteRequest(Irp, status, 0);

	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



	case IOCTL_SUBMIT_ITEM:				// code == 0x800

		{						// IOCTL_SUBMIT_ITEM

		if (cbout < sizeof(ULONG))

			status = STATUS_INVALID_PARAMETER;

		else

			status = GenericCacheControlRequest(pdx->pgx, Irp, &pdx->NotifyIrp);



		if (status != STATUS_PENDING)

			break;				// something wrong, so quit



		// Create an executive work item that will complete the notification IRP.

		// Since there's no way to cancel a queued work item, leave the remove

		// lock claim we already have in place and use the new IoXxxWorkItem routines

		// to protect the device object until all of our code has finished executing.



		// Link this driver with ntoskrnl.lib instead of wdm.lib because (at RC-2, anyway),

		// the latter didn't define the IoXxxWorkItem routines. To test this driver under

		// Win98, you must also have WDMSTUB.VXD installed.



		PRANDOM_JUNK junk = (PRANDOM_JUNK) ExAllocatePool(PagedPool, sizeof(RANDOM_JUNK));

		if (!junk)

			{

			KdPrint((DRIVERNAME " - ExAllocatePool failed to allocate %d bytes for RANDOM_JUNK structure\n", sizeof(RANDOM_JUNK)));

			status = STATUS_INSUFFICIENT_RESOURCES;

			break;

			}



		junk->DeviceExtension = pdx;

		junk->value = *(PULONG) Irp->AssociatedIrp.SystemBuffer;

		junk->nfyirp = Irp;		// only used in call to IoReleaseRemoveLock



		PIO_WORKITEM item = IoAllocateWorkItem(fdo);

		if (!item)

			{

			ExFreePool(junk);

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

			status = STATUS_INSUFFICIENT_RESOURCES;

			break;

			}



		junk->item = item;

		

		// Queue the work item for delayed execution. IoQueueWorkItem will take out an

		// extra reference to our device object that will persist until after the

		// callback routine returns, thereby preventing this driver from unloading before

		// the last instruction in this driver finishes executing.

		

		IoQueueWorkItem(item, (PIO_WORKITEM_ROUTINE) WorkItemCallback, DelayedWorkQueue, junk);

		KdPrint((DRIVERNAME " - Work item queued\n"));



		return STATUS_PENDING;

		}						// IOCTL_SUBMIT_ITEM



	default:

		status = STATUS_INVALID_DEVICE_REQUEST;

		break;



		}						// process request



	IoReleaseRemoveLock(&pdx->RemoveLock, Irp);

	return status == STATUS_PENDING ? status : CompleteRequest(Irp, status, info);

	}							// DispatchControl



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



#pragma PAGEDCODE



VOID WorkItemCallback(PDEVICE_OBJECT fdo, PRANDOM_JUNK junk)

	{							// WorkItemCallback

	PAGED_CODE();

	KdPrint((DRIVERNAME " - Work item callback has occurred\n"));

	PDEVICE_EXTENSION pdx = junk->DeviceExtension;

	ULONG value = junk->value;



	// Locate and complete the control IRP used for testing.



	PIRP nfyirp = GenericUncacheControlRequest(pdx->pgx, &pdx->NotifyIrp);



	if (nfyirp)

		{						// complete the notification IRP	

		*(PULONG) nfyirp->AssociatedIrp.SystemBuffer = junk->value;

		CompleteRequest(nfyirp, STATUS_SUCCESS, sizeof(ULONG));

		}						// complete the notification IRP



	// Release the remove lock to balance the acquisition done in DispatchControl.

	

	IoReleaseRemoveLock(&pdx->RemoveLock, junk->nfyirp);



	// Release the memory occupied by the work item



	IoFreeWorkItem(junk->item);



	// Finally, release our context structure



	ExFreePool(junk);

	}							// WorkItemCallback

⌨️ 快捷键说明

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