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

📄 pnpeventdevice.cpp

📁 windows 2000/xpWDM设备驱动程序开发光盘代码
💻 CPP
字号:
// PnPEventDevice.cpp
// Implementation of PnPEventDevice device class
//
// Generated by DriverWizard version DriverStudio 2.6.0 (Build 336)
// Requires Compuware's DriverWorks classes
//

#pragma warning(disable:4065) // Allow switch statement with no cases
		  
#include <vdw.h>
#include <initguid.h>
#include <wdmguid.h>

extern "C"
NTKERNELAPI
NTSTATUS
IoReportTargetDeviceChangeAsynchronous(
    IN PDEVICE_OBJECT PhysicalDeviceObject,
    IN PVOID NotificationStructure,  // always begins with a PLUGPLAY_NOTIFICATION_HEADER
    IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback	OPTIONAL,
    IN PVOID Context	OPTIONAL
    );

#include "..\PnPEventioctl.h"
#include "..\PnPEventDeviceinterface.h"
#include "PnPEvent.h"
#include "PnPEventDevice.h"
#pragma hdrstop("PnPEvent.pch")

extern PDRIVER_OBJECT  MyDriverObject;

PVOID InterfaceNotificationEntry = NULL;
PVOID FileNotificationEntry = NULL;
PFILE_OBJECT	TargetFileObject;
UNICODE_STRING	SymbolicLinkName;
GUID			TargetGuid=ReadWriteDevice_CLASS_GUID;
KIoWorkItem		m_pItem;

NTSTATUS OnPnpNotify(PPLUGPLAY_NOTIFICATION_HEADER p,IN PVOID Context);
VOID	 Workitem(PDEVICE_OBJECT DeviceObject, PVOID Context);

GUID PnPEventDevice_Guid = PnPEventDevice_CLASS_GUID;

PnPEventDevice::PnPEventDevice(PDEVICE_OBJECT Pdo, ULONG Unit) :
	KPnpDevice(Pdo, &PnPEventDevice_Guid)
{
	// Check constructor status
    if ( ! NT_SUCCESS(m_ConstructorStatus) )
	{
	    return;
	}

	// Remember our unit number
	m_Unit = Unit;

	// Initialize the lower device
	m_Lower.Initialize(this, Pdo);

    // Inform the base class of the lower edge device object
	SetLowerDevice(&m_Lower);

	// Initialize the PnP Policy settings to the "standard" policy
	SetPnpPolicy();

	m_pItem.Initialize(Pdo);		//初试化工作项
	IoRegisterPlugPlayNotification(
		EventCategoryDeviceInterfaceChange,
		PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
		&TargetGuid, MyDriverObject,
		(PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)OnPnpNotify,
		this, &InterfaceNotificationEntry);
	//注册内核模式接口通知,当ReadWrite实例的GUID接口被允许和禁止时,系统将
	//调用OnPnpNotify回调例程
}

PnPEventDevice::~PnPEventDevice()
{
	if (FileNotificationEntry)
	{	//释放文件句柄
		ObDereferenceObject(TargetFileObject);
		TargetFileObject = NULL;
		//ObDereferenceObject与IoGetDeviceObjectPointer相对应,释放文件句柄,
		//否则系统卸载不掉ReadWrite
	}
	if (FileNotificationEntry)
	{	//注销句柄通知
		IoUnregisterPlugPlayNotification(FileNotificationEntry);
		FileNotificationEntry = NULL;
	}
	if (InterfaceNotificationEntry)
	{	//注销接口通知
		IoUnregisterPlugPlayNotification(InterfaceNotificationEntry);
		InterfaceNotificationEntry = NULL;
	}
}

NTSTATUS PnPEventDevice::DefaultPnp(KIrp I) 
{
	I.ForceReuseOfCurrentStackLocationInCalldown();
	return m_Lower.PnpCall(this, I);
}

NTSTATUS PnPEventDevice::DefaultPower(KIrp I) 
{
	I.IndicatePowerIrpProcessed();
	I.CopyParametersDown();
	return m_Lower.PnpPowerCall(this, I);
}

NTSTATUS PnPEventDevice::SystemControl(KIrp I) 
{
	I.ForceReuseOfCurrentStackLocationInCalldown();
	return m_Lower.PnpCall(this, I);
}

NTSTATUS PnPEventDevice::OnStartDevice(KIrp I)
{
	return STATUS_SUCCESS;
}

NTSTATUS PnPEventDevice::OnStopDevice(KIrp I)
{
	return STATUS_SUCCESS;
}

NTSTATUS PnPEventDevice::OnRemoveDevice(KIrp I)
{
	return STATUS_SUCCESS;
}

NTSTATUS PnPEventDevice::Create(KIrp I)
{
	return I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
}

NTSTATUS PnPEventDevice::Close(KIrp I)
{
	return I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
}

NTSTATUS PnPEventDevice::DeviceControl(KIrp I) 
{
	NTSTATUS status;
	switch (I.IoctlCode())
	{
		case PNPEVENT_IOCTL_800:
			TARGET_DEVICE_CUSTOM_NOTIFICATION notify;
			notify.Version = 1;
			notify.Size = sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION) + sizeof(ULONG) - sizeof(UCHAR);
			notify.Event = GUID_PNPEVENT_EVENT;
			notify.FileObject = NULL;
			notify.NameBufferOffset = 0;
			*((PULONG) (&(notify.CustomDataBuffer[0]))) = 0;
			status = IoReportTargetDeviceChangeAsynchronous(m_Lower.PDO(), &notify, NULL, NULL);
			//生成一个定制通知
			if (NT_SUCCESS(status))
				status = STATUS_SUCCESS; 
			else
				status = STATUS_UNSUCCESSFUL;
			break;

		default:
			// Unrecognized IOCTL request
			status = STATUS_INVALID_PARAMETER;
			break;
	}

	return I.PnpComplete(this, status);
}

NTSTATUS OnPnpNotify(PPLUGPLAY_NOTIFICATION_HEADER p,IN PVOID Context)
{	//处理内核模式的接口和句柄通知
	PDEVICE_INTERFACE_CHANGE_NOTIFICATION q=NULL;

	if (p->Event == GUID_DEVICE_INTERFACE_ARRIVAL)
	{	//接口允许通知
		DbgPrint("arrival\n");
		q = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION) p;
		SymbolicLinkName.MaximumLength = q->SymbolicLinkName->MaximumLength;
		SymbolicLinkName.Length = 0;
		SymbolicLinkName.Buffer = (PWSTR)ExAllocatePool(
			PagedPool, SymbolicLinkName.MaximumLength); //申请分配内存
		if( SymbolicLinkName.Buffer!=NULL)
		{
			RtlCopyUnicodeString(&SymbolicLinkName,q->SymbolicLinkName);
			//拷贝设备符号链接名
			PnPEventDevice* m_pnp=(PnPEventDevice*)Context;
			m_pnp->IncrementOutstandingRequestCount();
			//增加未决IRP数目,在工作项完成之前,防止设备删除
			m_pItem.Queue(Workitem,Context);	//排队工作项
		}
	}
	else if (p->Event == GUID_DEVICE_INTERFACE_REMOVAL)
		DbgPrint("removal\n");	//接口禁止通知
	//以下均为句柄通知
	else if (p->Event == GUID_TARGET_DEVICE_QUERY_REMOVE)
	{
		DbgPrint("target query remove\n");
		if (FileNotificationEntry)
		{
			ObDereferenceObject(TargetFileObject);
			TargetFileObject = NULL;
			//释放文件句柄
		}
	}
	else if (p->Event == GUID_TARGET_DEVICE_REMOVE_CANCELLED)
		DbgPrint("target remove cancelled\n");
	else if (p->Event == GUID_TARGET_DEVICE_REMOVE_COMPLETE)
	{
		DbgPrint("target remove complete\n");
		IoUnregisterPlugPlayNotification(FileNotificationEntry);
		FileNotificationEntry = NULL;
		//注销句柄通知
	}
	else 
		DbgPrint("custom notification");

	return STATUS_SUCCESS;
}

VOID Workitem(PDEVICE_OBJECT DeviceObject, PVOID Context)
{
	NTSTATUS status;

	PDEVICE_OBJECT junk;
	status = IoGetDeviceObjectPointer(
		&SymbolicLinkName, 0, &TargetFileObject, &junk);
	//根据设备符号链接名获取其设备对象和文件对象指针
	if (NT_SUCCESS(status))
	{	// register for notifications
		IoRegisterPlugPlayNotification(
			EventCategoryTargetDeviceChange, 0,
			TargetFileObject, MyDriverObject,
			(PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) OnPnpNotify,
			NULL, &FileNotificationEntry);
	}
	//注册内核模式句柄通知,当ReadWrite实例发生PnP事件时,系统将调用
	//OnPnpNotify回调例程
	if( SymbolicLinkName.Buffer!=NULL)
		ExFreePool(SymbolicLinkName.Buffer);	//释放申请的内存
	PnPEventDevice* m_pnp=(PnPEventDevice*)Context;
	m_pnp->DecrementOutstandingRequestCount();	//减少未决IRP数目
}

⌨️ 快捷键说明

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