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

📄 readwrite.cpp

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

// Copyright (C) 1999 by Walter Oney

// All rights reserved



#include "stddcls.h"

#include "driver.h"



#if DBG

	#define MSGUSBSTRING(d,s,i) { \

		UNICODE_STRING sd; \

		if (i && NT_SUCCESS(GetStringDescriptor(d,i,&sd))) { \

			DbgPrint(s, sd.Buffer); \

			RtlFreeUnicodeString(&sd); \

		}}

#else

	#define MSGUSBSTRING(d,i,s)

#endif



NTSTATUS StartInterruptUrb(PDEVICE_EXTENSION pdx);

NTSTATUS OnInterrupt(PDEVICE_OBJECT junk, PIRP Irp, PDEVICE_EXTENSION pdx);

VOID StopInterruptUrb(PDEVICE_EXTENSION pdx);



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



#pragma PAGEDCODE



NTSTATUS CreateInterruptUrb(PDEVICE_OBJECT fdo)

	{							// CreateInterruptUrb

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	ASSERT(pdx->PollingIrp == NULL);

	ASSERT(pdx->PollingUrb == NULL);



	PIRP Irp = IoAllocateIrp(pdx->LowerDeviceObject->StackSize, FALSE);

	if (!Irp)

		{

		KdPrint((DRIVERNAME " - Unable to create IRP for interrupt polling\n"));

		return STATUS_INSUFFICIENT_RESOURCES;

		}



	PURB urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER));

	if (!urb)

		{

		KdPrint((DRIVERNAME " - Unable to allocate interrupt polling URB\n"));

		IoFreeIrp(Irp);

		return STATUS_INSUFFICIENT_RESOURCES;

		}



	pdx->PollingIrp = Irp;

	pdx->PollingUrb = urb;



	return STATUS_SUCCESS;

	}							// CreateInterruptUrb



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



#pragma PAGEDCODE



VOID DeleteInterruptUrb(PDEVICE_OBJECT fdo)

	{							// DeleteInterruptUrb

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	ASSERT(pdx->PollingIrp != NULL);

	ASSERT(pdx->PollingUrb != NULL);



	ExFreePool(pdx->PollingUrb);

	IoFreeIrp(pdx->PollingIrp);

	pdx->PollingIrp = NULL;

	pdx->PollingUrb = NULL;

	}							// DeleteInterruptUrb



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



#pragma PAGEDCODE



NTSTATUS DispatchCleanup(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchCleanup

	PAGED_CODE();

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

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;



	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);



	GenericCleanupControlRequests(pdx->pgx, STATUS_CANCELLED, stack->FileObject);



	return CompleteRequest(Irp, STATUS_SUCCESS, 0);

	}							// DispatchCleanup



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



#pragma PAGEDCODE



NTSTATUS DispatchCreate(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchCreate

	PAGED_CODE();

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

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;



	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);



	// Only allow one handle at a time because we only have one place to

	// remember the pending IOCTL we use for notifying the application that

	// an interrupt has occurred.



	if (InterlockedIncrement(&pdx->handles) > 1)

		{						// too many opens

		InterlockedDecrement(&pdx->handles);

		return CompleteRequest(Irp, STATUS_ACCESS_DENIED, 0);

		}						// too many opens



	return CompleteRequest(Irp, STATUS_SUCCESS, 0);

	}							// DispatchCreate



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



#pragma PAGEDCODE



NTSTATUS DispatchClose(PDEVICE_OBJECT fdo, PIRP Irp)

	{							// DispatchClose

	PAGED_CODE();

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

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);



	// The cleanup routine should have gotten rid of any pending

	// WAITINT operation



	ASSERT(pdx->InterruptIrp == NULL);



	InterlockedDecrement(&pdx->handles);



	return CompleteRequest(Irp, STATUS_SUCCESS, 0);

	}							// DispatchClose



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

// GENERIC calls this function to decide what device power state to enter for

// a given system state. We want our device fully powered at all times, so

// we need to provide this callback.



#pragma LOCKEDCODE



DEVICE_POWER_STATE GetDevicePowerState(PDEVICE_OBJECT fdo, SYSTEM_POWER_STATE sstate, DEVICE_POWER_STATE dstate)

	{							// GetDevicePowerState

	if (sstate == PowerSystemWorking)

		return PowerDeviceD0;

	return dstate;

	}							// GetDevicePowerState



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



#pragma PAGEDCODE



NTSTATUS GetStringDescriptor(PDEVICE_OBJECT fdo, UCHAR istring, PUNICODE_STRING s)

	{							// GetStringDescriptor

	NTSTATUS status;

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	URB urb;



	UCHAR data[256];			// maximum-length buffer



	// If this is the first time here, read string descriptor zero and arbitrarily select

	// the first language identifer as the one to use in subsequent get-descriptor calls.



	if (!pdx->langid)

		{						// determine default language id

		UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE,

			0, 0, data, NULL, sizeof(data), NULL);

		status = SendAwaitUrb(fdo, &urb);

		if (!NT_SUCCESS(status))

			return status;

		pdx->langid = *(LANGID*)(data + 2);

		}						// determine default language id



	// Fetch the designated string descriptor.



	UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE,

		istring, pdx->langid, data, NULL, sizeof(data), NULL);

	status = SendAwaitUrb(fdo, &urb);

	if (!NT_SUCCESS(status))

		return status;



	ULONG nchars = (data[0] - sizeof(WCHAR)) / sizeof(WCHAR);

	if (nchars > 127)

		nchars = 127;

	PWSTR p = (PWSTR) ExAllocatePool(PagedPool, (nchars + 1) * sizeof(WCHAR));

	if (!p)

		return STATUS_INSUFFICIENT_RESOURCES;



	memcpy(p, data + 2, nchars * sizeof(WCHAR));

	p[nchars] = 0;



	s->Length = (USHORT) (sizeof(WCHAR) * nchars);

	s->MaximumLength = (USHORT) ((sizeof(WCHAR) * nchars) + sizeof(WCHAR));

	s->Buffer = p;



	return STATUS_SUCCESS;

	}							// GetStringDescriptor



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

// This is the completion routine for a read operation on the interrupt pipe.



#pragma LOCKEDCODE



NTSTATUS OnInterrupt(PDEVICE_OBJECT junk, PIRP Irp, PDEVICE_EXTENSION pdx)

	{							// OnInterrupt



	KIRQL oldirql;

	KeAcquireSpinLock(&pdx->polllock, &oldirql);

	pdx->pollpending = FALSE;		// allow another poll to be started

	PVOID powercontext = pdx->powercontext;

	pdx->powercontext = NULL;

	KeReleaseSpinLock(&pdx->polllock, oldirql);



	// If the poll completed successfully, do whatever it is we do when we

	// get an interrupt (in this sample, that's answering an IOCTL) and

	// reissue the read. We're trying to have a read outstanding on the

	// interrupt pipe all the time except when power is off.



	if (NT_SUCCESS(Irp->IoStatus.Status))

		{						// device signalled an interrupt

		KdPrint((DRIVERNAME " - Interrupt!\n"));



		PIRP intirp = GenericUncacheControlRequest(pdx->pgx, &pdx->InterruptIrp);

		if (intirp)

			CompleteRequest(intirp, STATUS_SUCCESS, 0);

		else

			InterlockedIncrement(&pdx->numints);



		// Unless we're in the middle of a power-off sequence, reissue the

		// polling IRP. Normally, SaveContext would have tried to cancel the

		// IRP, and we won't get to this statement because STATUS_CANCELLED

		// will fail the NT_SUCCESS test. We don't have any guarantee that the

		// IRP will actually complete with STATUS_CANCELLED, though. Hence this test.

		

		if (!powercontext)

			StartInterruptUrb(pdx); // issue next polling request

		}						// device signalled an interrupt

#if DBG	

	else

		{

		KdPrint((DRIVERNAME " - Interrupt polling IRP %X failed - %X (USBD status %X)\n",

			Irp, Irp->IoStatus.Status, URB_STATUS(pdx->PollingUrb)));

		}

#endif



	// If we cancelled the poll during a power-down sequence, notify our

	// power management code that it can continue.



	if (powercontext)

		GenericSaveRestoreComplete(powercontext);



	IoReleaseRemoveLock(&pdx->RemoveLock, Irp); // balances acquisition in StartInterruptUrb



	return STATUS_MORE_PROCESSING_REQUIRED;

	}							// OnInterrupt



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

// GENERIC calls this function as part of restoring power to the device. We

// use the opportunity to restart the interrupt polling URB.



#pragma LOCKEDCODE



VOID RestoreContext(PDEVICE_OBJECT fdo, DEVICE_POWER_STATE oldstate, DEVICE_POWER_STATE newstate, PVOID context)

	{							// RestoreContext



	// If power is on, make sure we have a read outstanding on our interrupt pipe



	if (newstate == PowerDeviceD0)

		StartInterruptUrb((PDEVICE_EXTENSION) fdo->DeviceExtension);



	// Notify the power management code that we're done with this operation



	GenericSaveRestoreComplete(context);

	}							// RestoreContext



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

// GENERIC calls this function as part of lowering power to the device.  We

// use the opportunity to cancel the polling URB.



#pragma LOCKEDCODE



VOID SaveContext(PDEVICE_OBJECT fdo, DEVICE_POWER_STATE oldstate, DEVICE_POWER_STATE newstate, PVOID context)

	{							// SaveContext

	ASSERT(context);



	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;



	// If device is losing power, cancel any pending interrupt poll operation.

	// Defer the power operation until the cancel finishes



	if (newstate > PowerDeviceD0)

		{						// losing power

		KIRQL oldirql;

		KeAcquireSpinLock(&pdx->polllock, &oldirql);

		if (pdx->pollpending)

			{					// cancel poll

			pdx->powercontext = context;

			IoCancelIrp(pdx->PollingIrp);

			KeReleaseSpinLock(&pdx->polllock, oldirql);

⌨️ 快捷键说明

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