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

📄 intrdev.cpp

📁 Windows 2000/XP WDM設備驅動程式開發 使用 Numega 公司出版的軟體快速建置驅動程式
💻 CPP
字号:
// intrdev.cpp - implementation of interrupt demo device class 
//=============================================================================
//
// Compuware Corporation
// NuMega Lab
// 9 Townsend West
// Nashua, NH 03060  USA
//
// Copyright (c) 1998 Compuware Corporation. All Rights Reserved.
// Unpublished - rights reserved under the Copyright laws of the
// United States.
//
//=============================================================================

#include <vdw.h>
#include "common.h"
#include "intrdev.h"

// Class InterruptDemoDevice hooks IRQ 6, which is the floppy
// interrupt on Intel platforms. The device does not hook the
// interrupt until the test application opens it, and member
// Create is called. The ISR takes a time stamp, writes a record to
// a FIFO, and queues a DPC. The DPC notifies the test app that an
// interrupt has occurred by setting an event whose handle had
// been previously sent to the device using DeviceIoControl. The
// DPC does not set the event if the app has not responded to a
// previous event. The app retrieves the records written to the
// FIFO by the ISR using another DeviceIoControl call.

KDebugOnlyTrace T("IntrDemo");

#define DRIVER_EVENT_NAME L"\\BaseNamedObjects\\SynchEvent"

//////////////////////////////////////////////////////////////////
// Device class constructor
//
InterruptDemoDevice::~InterruptDemoDevice()
{
	T << "Deleting device\n";

	if (m_pEvent)
		delete m_pEvent;

	if ((PKINTERRUPT)m_Interrupt)
		m_Interrupt.Disconnect();
}

//////////////////////////////////////////////////////////////////
// Begin INIT section code
#pragma code_seg("INIT")

//////////////////////////////////////////////////////////////////
// Device class constructor
//
InterruptDemoDevice::InterruptDemoDevice() :

// Base class
	KDevice(
		L"IntrDemo0", 
		FILE_DEVICE_UNKNOWN, 
		L"IntrDemo0", 
		DO_BUFFERED_IO
		),

// Interrupt object
	m_Interrupt(
		Isa,
		0,
		FLOPPY_IRQ,
		FLOPPY_IRQ,
		Latched,
		TRUE,
		FALSE
	),

// Output fifo
	m_TimeStampFifo(FIFOSIZE, NonPagedPool)

{
	m_File = 0;
	m_pEvent = NULL;
	m_bNotifyApp = TRUE;
	m_Dpc.Setup(LinkTo(Dpc), this);
	m_InterruptCount = 0;
}
#pragma code_seg()

//////////////////////////////////////////////////////////////////
// Create 
//
// This is called when the test app issues a CreateFile
//
NTSTATUS InterruptDemoDevice::Create(KIrp I)
{
	NTSTATUS status;

	if (m_File == 0)
	{
		m_File = I.FileObject();
		status = m_Interrupt.Connect(LinkTo(Isr), this);
	}
	else
		status = STATUS_UNSUCCESSFUL;

	m_pEvent = new (NonPagedPool) KEvent(KUstring(DRIVER_EVENT_NAME),SynchronizationEvent);
	if (m_pEvent != NULL) m_pEvent->Clear(); 
	else
	{
		m_Interrupt.Disconnect();
		m_File = 0;
		status = STATUS_UNSUCCESSFUL;
	}
	T << "Create status = " << ULONG(status) << "\n";
	
	I.Information() = 0;
	return I.Complete(status);
}

//////////////////////////////////////////////////////////////////
// Close
//
// This is called when the test app closes the handle to the device
//
NTSTATUS InterruptDemoDevice::Close(KIrp I)
{
	NTSTATUS status;

	I.Information() = 0;

	if (m_File == I.FileObject())
	{
		T << "Disconnecting interrupt\n";
		m_Interrupt.Disconnect();
		m_File = 0;
		if (m_pEvent) delete m_pEvent;
		m_pEvent = NULL;
		status = STATUS_SUCCESS;
	}
	else
		status = STATUS_UNSUCCESSFUL;

	return I.Complete(status);
}

NTSTATUS InterruptDemoDevice::DeviceControl(KIrp I)
{
	T << I;
	
	I.Information() = 0;

	switch (I.IoctlCode())
	{
	case IOCTL_GET_TIMESTAMP_DATA:
		if (SynchronizeInterrupt(&m_Interrupt, LinkTo(ReadTimeFifo), PIRP(I)) )
			return I.Complete(STATUS_SUCCESS);

		else
			return I.Complete(STATUS_UNSUCCESSFUL);

		break;

	default:
		T << "Bad Request: " << I.IoctlCode() << "\n";

		return I.Complete(STATUS_INVALID_PARAMETER);	
	}
}

BOOLEAN InterruptDemoDevice::Isr(void)
{
	T << "In the ISR\n";

	TIMESTAMP ts;

	ts.ts_interrupt_count = ++m_InterruptCount;
	KeQueryTickCount(&ts.ts_time);

	m_TimeStampFifo.Write(&ts, 1);

	m_Dpc.Request();
	return FALSE;
}

VOID InterruptDemoDevice::Dpc(PVOID Arg1, PVOID Arg2)
{
	BOOLEAN Notify;
	BOOLEAN SynchStatus;

	if (m_pEvent) 
	{
		SynchStatus = SynchronizeInterrupt(
			&m_Interrupt, 
			LinkTo(TestAndClearNotifyApp), 
			&Notify
			);

		if (SynchStatus)
		{
			T << "DPC, App notify=" << ULONG(Notify) << "\n";
			if (Notify) 
				m_pEvent->Set();
		}
		else
			T << "Dpc error synchronizing\n";
	}
}

BOOLEAN InterruptDemoDevice::ReadTimeFifo(PVOID pIrp)
{
	KIrp I = (PIRP)pIrp;
	ULONG MaxReadItems = I.IoctlOutputBufferSize() / sizeof(TIMESTAMP);
	ULONG nItemsRead;

	nItemsRead = m_TimeStampFifo.Read((TIMESTAMP*)I.IoctlBuffer(), MaxReadItems);
	// guaranteed to empty the buffer, because app's read buffer is sizeof the fifo

	I.Information() = nItemsRead * sizeof(TIMESTAMP);

	m_bNotifyApp = TRUE;

	return TRUE;
}

BOOLEAN InterruptDemoDevice::TestAndClearNotifyApp(PVOID p)
{
	*(BOOLEAN*)p = m_bNotifyApp;
	m_bNotifyApp = FALSE;

	T << "TestAndClearNotifyApp previous state was=" << ULONG(m_bNotifyApp) << "\n";

	return TRUE;
}

⌨️ 快捷键说明

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