wdm驱动,通过IRP_MN_QUERY_CAPABILITIES实现设备通过任务栏的绿色箭头弹出

电源事件相关的IRP包括 IRP_MJ_POWER和IRP_MN_QUERY_CAPABILITIES 此处关于IRP_MN_QUERY_CAPABILITIES的使用FDO通过向底层PDO请求此IRP,会得到 DEVICE_CAPABILITIES结构体数据,此结构体会指明驱动程序支持的电源特新。

驱动代码:

///
///
/// Copyright (c) 2014 - <company name here>
///
/// Original filename: HelloWdm.cpp
/// Project          : HelloWdm
/// Date of creation : 2014-07-02
/// Author(s)        : <author name(s)>
///
/// Purpose          : <description>
///
/// Revisions:
///  0000 [2014-07-02] Initial revision.
///
///

// $Id$

#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <string.h>
#ifdef __cplusplus
}; // extern "C"
#endif

#include "HelloWdm.h"

static const GUID WdmHello1 = { 0xf8f8064c, 0xee05, 0x41ea, { 0x99, 0xd5, 0x55, 0x36, 0x5a, 0xb8, 0x17, 0x18 } };
// {F8F8064C-EE05-41ea-99D5-55365AB81718}


typedef struct _DEVICE_EXTENSION 
{
	PDEVICE_OBJECT pFdo;
	PDEVICE_OBJECT pNextStackDev;
	UNICODE_STRING interfaceName;

}DEVICE_EXTENSION,*PDEVICE_EXTENSION;


#pragma code_seg("PAGE")
NTSTATUS
OnCompleteRoutine(
				  __in PDEVICE_OBJECT  DeviceObject,
				  __in PIRP  Irp,
				  __in PVOID  Context
				  )
{

	KdPrint(("OnCompleteRoutine Enter...."));


	PKEVENT pKevent = (PKEVENT)Context;
	KeSetEvent(pKevent,IO_NO_INCREMENT,FALSE);

	KdPrint(("OnCompleteRoutine Leave...."));


	return STATUS_MORE_PROCESSING_REQUIRED;
}



#pragma code_seg("PAGE")

NTSTATUS
ForwardAndWait(PDEVICE_EXTENSION   pdx, PIRP  Irp)

{

	KdPrint(("ForwardAndWait Enter...."));


	NTSTATUS status = STATUS_UNSUCCESSFUL;
	//初始化一个事件
	KEVENT kEvent;
	KeInitializeEvent(&kEvent,NotificationEvent,FALSE);

	//赋值irp到下层堆栈
	IoCopyCurrentIrpStackLocationToNext(Irp);

	//设置完成例程
	IoSetCompletionRoutine(Irp,OnCompleteRoutine,&kEvent,TRUE,TRUE,TRUE);

	//调用底层驱动

	status = IoCallDriver(pdx->pNextStackDev,Irp);


	//等待完成例程返回
	KeWaitForSingleObject(&kEvent,Executive,KernelMode,FALSE,NULL);

	KdPrint(("ForwardAndWait Leave...."));

	return Irp->IoStatus.Status;
}





NTSTATUS HELLOWDM_DispatchCreateClose(
    IN PDEVICE_OBJECT		DeviceObject,
    IN PIRP					Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS HELLOWDM_DispatchDeviceControl(
    IN PDEVICE_OBJECT		DeviceObject,
    IN PIRP					Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);

    switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_HELLOWDM_OPERATION:
        // status = SomeHandlerFunction(irpSp);
        break;
    default:
        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Information = 0;
        break;
    }

    status = Irp->IoStatus.Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}

VOID HELLOWDM_DriverUnload(
    IN PDRIVER_OBJECT		DriverObject
    )
{
    KdPrint(("HELLOWDM_DriverUnload...."));
}



NTSTATUS HelloWdmAddDevice(PDRIVER_OBJECT pDriverObj,PDEVICE_OBJECT pPhysicalDeviceObj)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;

	PDEVICE_OBJECT pFdo;

	status = IoCreateDevice(pDriverObj,sizeof(DEVICE_EXTENSION),NULL,FILE_DEVICE_UNKNOWN,0,FALSE,&pFdo);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("IoCreateDevice Error:0x%x",status));
		return status;
	}

	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pFdo->DeviceExtension;
	pDevExt->pFdo =   pFdo;

	pDevExt->pNextStackDev = IoAttachDeviceToDeviceStack(pFdo,pPhysicalDeviceObj);
	if (pDevExt->pNextStackDev == NULL)
	{
		KdPrint(("IoAttachDeviceToDeviceStack Error:0x%x",status));
		IoDeleteDevice(pFdo);
		return status;
	}


	status = IoRegisterDeviceInterface(pPhysicalDeviceObj,&WdmHello1,NULL,&pDevExt->interfaceName);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("IoRegisterDeviceInterface Error:0x%x",status));
		IoDeleteDevice(pFdo);
		return status;
	}

	KdPrint(("%wZ\n",&pDevExt->interfaceName));

	status = IoSetDeviceInterfaceState(&pDevExt->interfaceName,TRUE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("IoSetDeviceInterfaceState Error:0x%x",status));
		IoDeleteDevice(pFdo);
		return status;

	}


	//设置缓冲区方式
	pFdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
	pFdo->Flags &= ~DO_DEVICE_INITIALIZING;


	return /*status*/STATUS_SUCCESS;

}



#pragma  code_seg("PAGE")
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx,PIRP irp)
{

 	IoSkipCurrentIrpStackLocation(irp);
 	return IoCallDriver(pdx->pNextStackDev,irp);
}



#define SetMostPoweredState( SystemState, OurDeviceState)	\
	dps = pDevCap->DeviceState[SystemState];		\
	if( dps==PowerDeviceUnspecified || dps>OurDeviceState)	\
	pDevCap->DeviceState[SystemState] = OurDeviceState


#pragma  code_seg("PAGE")
NTSTATUS PnpQueryCapabilitiesHandler(PDEVICE_EXTENSION pdx,PIRP irp)
{

	
	
	/*
	电源事件相关的IRP包括 IRP_MJ_POWER和IRP_MN_QUERY_CAPABILITIES
	此处关于IRP_MN_QUERY_CAPABILITIES的使用FDO通过向底层PDO请求此IRP,会得到
	DEVICE_CAPABILITIES结构体数据,此结构体会指明驱动程序支持的电源特新。
	*/

	NTSTATUS status = STATUS_UNSUCCESSFUL;

	status = ForwardAndWait(pdx,irp);
	if (NT_SUCCESS(status))
	{
		PIO_STACK_LOCATION pCurrStack = IoGetCurrentIrpStackLocation(irp);
		PDEVICE_CAPABILITIES pDevCap = pCurrStack->Parameters.DeviceCapabilities.Capabilities;

		for (int i=PowerSystemWorking;i<PowerSystemMaximum;i++)
		{
			KdPrint(("capabilities from bus :DeviceState[%d]:%d",i,pDevCap->DeviceState[i]));
		}

		DEVICE_POWER_STATE dps;
		SetMostPoweredState(PowerSystemWorking,PowerDeviceD0);
		SetMostPoweredState(PowerSystemSleeping1,PowerDeviceD3);
		SetMostPoweredState(PowerSystemSleeping2,PowerDeviceD3);
		SetMostPoweredState(PowerSystemSleeping3,PowerDeviceD3);
		SetMostPoweredState(PowerSystemShutdown,PowerDeviceD3);

		//重点
		pDevCap->Removable = TRUE;//支持热插拔

		//下面2项不用设置
		//pDevCap->SurpriseRemovalOK = TRUE;//支持热插拔,意外拔出
		//pDevCap->EjectSupported = TRUE;//支持热插拔,是否可弹出

		for (int i=PowerSystemWorking;i<PowerSystemMaximum;i++)
		{
			KdPrint(("capabilities Now :DeviceState[%d]:%d",i,pDevCap->DeviceState[i]));
		}


	}

	
	irp->IoStatus.Status = status;
	irp->IoStatus.Status = 0;
	IoCompleteRequest(irp,IO_NO_INCREMENT);

	return status;

}


#pragma code_seg("PAGE")
VOID ShowResources(PCM_PARTIAL_RESOURCE_LIST list)
{

	if (list == NULL)
	{
		return;
	}
	//枚举资源
	PCM_PARTIAL_RESOURCE_DESCRIPTOR pListDesc = list->PartialDescriptors;
	ULONG uRes = list->Count;
	ULONG i = 0;

	for(int i =0;i<uRes;++i,pListDesc++)
	{
		//对每一种资源进行枚举
		ULONG uTyep = pListDesc->Type;
		KdPrint(("ShowResources uTyep:%d\n",uTyep));
		switch (uTyep)
		{
			//物理资源
		case CmResourceTypePort:			
		case CmResourceTypeMemory:
			{
				KdPrint(("start:%8X%8.8lX Length: %X\n",pListDesc->u.Port.Start.HighPart,
					pListDesc->u.Port.Start.HighPart,pListDesc->u.Port.Length));
			}
			break;
			//中断
		case CmResourceTypeInterrupt:
			{

				KdPrint(("Level:%X  Vector:%X   Affinity:%X\n",pListDesc->u.Interrupt.Level,
					pListDesc->u.Interrupt.Vector,pListDesc->u.Interrupt.Affinity));
			}
			break;
			//DMA
		case CmResourceTypeDma:
			{
				KdPrint(("Channel:%X,PORT:%X\n",pListDesc->u.Dma.Channel,pListDesc->u.Dma.Port));

			}
			break;

		}

	}

}




#pragma  code_seg("PAGE")
NTSTATUS HandleStartDevice(PDEVICE_EXTENSION pdx,PIRP irp)
{

	KdPrint(("HandleStartDevice Enter...."));

	NTSTATUS status = STATUS_UNSUCCESSFUL;

	
	status = ForwardAndWait(pdx,irp);
	if (!NT_SUCCESS(status))//非成功的情况下,直接完成IRP
	{
		irp->IoStatus.Status = status;
		IoCompleteRequest(irp,IO_NO_INCREMENT);
		return status;
	}

	PIO_STACK_LOCATION pCurrStack = IoGetCurrentIrpStackLocation(irp);

	//从当前栈获取源信息
	PCM_PARTIAL_RESOURCE_LIST raw;
	if (pCurrStack->Parameters.StartDevice.AllocatedResources)
	{
		raw = &pCurrStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
	}else
	{
		raw = NULL;
	}

	//显示PCI资源
	ShowResources(raw);

	//从当前栈获取翻译信息
	PCM_PARTIAL_RESOURCE_LIST tranlated;
	if (pCurrStack->Parameters.StartDevice.AllocatedResourcesTranslated)
	{
		tranlated = &pCurrStack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
	}else
	{
		tranlated = NULL;
	}

	//显示PCI资源
	ShowResources(tranlated);



	irp->IoStatus.Status = status;
	IoCompleteRequest(irp,IO_NO_INCREMENT);
	//因为完成例程返回STATUS_MORE_PROCEING_REQUIRED,需要再次完成IRP

	KdPrint(("HandleStartDevice Leave...."));


	return status;

}


#pragma  code_seg("PAGE")
NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx,PIRP irp)
{

	KdPrint(("HandleRemoveDevice enter"));

	NTSTATUS status = STATUS_UNSUCCESSFUL;
	
	irp->IoStatus.Status = STATUS_SUCCESS;
	status = DefaultPnpHandler(pdx,irp);

	IoSetDeviceInterfaceState(&pdx->interfaceName,FALSE);

	RtlFreeUnicodeString(&pdx->interfaceName);

	//把FDO从设备栈脱开
	if (pdx->pNextStackDev)
	{
		IoDetachDevice(pdx->pNextStackDev);
	}

	//删除FDO
	IoDeleteDevice(pdx->pFdo);

	KdPrint(("HandleRemoveDevice leave"));

	return status;

}


#define  arraySize(p)  (sizeof(p)/sizeof(p[0]))


NTSTATUS HelloWdmPnp(PDEVICE_OBJECT pDeviceObj,PIRP pIrp)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	PAGED_CODE();//Checked模式下有效,确保运行在irql足够低,允许分页的级别

	KdPrint(("HelloWdmPnp Enter..."));

	//获得设备扩展
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDeviceObj->DeviceExtension;

	//获得当前IO栈
	PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);

	static NTSTATUS (*FunTab[])(PDEVICE_EXTENSION ,PIRP ) = {

		HandleStartDevice,		// IRP_MN_START_DEVICE
		DefaultPnpHandler,		// IRP_MN_QUERY_REMOVE_DEVICE
		HandleRemoveDevice,		// IRP_MN_REMOVE_DEVICE
		DefaultPnpHandler,		// IRP_MN_CANCEL_REMOVE_DEVICE
		DefaultPnpHandler,		// IRP_MN_STOP_DEVICE
		DefaultPnpHandler,		// IRP_MN_QUERY_STOP_DEVICE
		DefaultPnpHandler,		// IRP_MN_CANCEL_STOP_DEVICE
		DefaultPnpHandler,		// IRP_MN_QUERY_DEVICE_RELATIONS
		DefaultPnpHandler,		// IRP_MN_QUERY_INTERFACE
		PnpQueryCapabilitiesHandler,		// IRP_MN_QUERY_CAPABILITIES
		DefaultPnpHandler,		// IRP_MN_QUERY_RESOURCES
		DefaultPnpHandler,		// IRP_MN_QUERY_RESOURCE_REQUIREMENTS
		DefaultPnpHandler,		// IRP_MN_QUERY_DEVICE_TEXT
		DefaultPnpHandler,		// IRP_MN_FILTER_RESOURCE_REQUIREMENTS
		DefaultPnpHandler,		// 
		DefaultPnpHandler,		// IRP_MN_READ_CONFIG
		DefaultPnpHandler,		// IRP_MN_WRITE_CONFIG
		DefaultPnpHandler,		// IRP_MN_EJECT
		DefaultPnpHandler,		// IRP_MN_SET_LOCK
		DefaultPnpHandler,		// IRP_MN_QUERY_ID
		DefaultPnpHandler,		// IRP_MN_QUERY_PNP_DEVICE_STATE
		DefaultPnpHandler,		// IRP_MN_QUERY_BUS_INFORMATION
		DefaultPnpHandler,		// IRP_MN_DEVICE_USAGE_NOTIFICATION
		DefaultPnpHandler,		// IRP_MN_SURPRISE_REMOVAL

	};

	

	ULONG uFunc = pStack->MinorFunction;
	if (uFunc >= arraySize(FunTab))
	{
		status = DefaultPnpHandler(pDevExt,pIrp);
		return status;
	}


	static char* fcnname[] = 
	{
		"IRP_MN_START_DEVICE",
		"IRP_MN_QUERY_REMOVE_DEVICE",
		"IRP_MN_REMOVE_DEVICE",
		"IRP_MN_CANCEL_REMOVE_DEVICE",
		"IRP_MN_STOP_DEVICE",
		"IRP_MN_QUERY_STOP_DEVICE",
		"IRP_MN_CANCEL_STOP_DEVICE",
		"IRP_MN_QUERY_DEVICE_RELATIONS",
		"IRP_MN_QUERY_INTERFACE",
		"IRP_MN_QUERY_CAPABILITIES",
		"IRP_MN_QUERY_RESOURCES",
		"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
		"IRP_MN_QUERY_DEVICE_TEXT",
		"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
		"",
		"IRP_MN_READ_CONFIG",
		"IRP_MN_WRITE_CONFIG",
		"IRP_MN_EJECT",
		"IRP_MN_SET_LOCK",
		"IRP_MN_QUERY_ID",
		"IRP_MN_QUERY_PNP_DEVICE_STATE",
		"IRP_MN_QUERY_BUS_INFORMATION",
		"IRP_MN_DEVICE_USAGE_NOTIFICATION",
		"IRP_MN_SURPRISE_REMOVAL",
	};


	KdPrint(("PNP Request uFunc:%d (%s)\n",uFunc, fcnname[uFunc]));


	status = (*FunTab[uFunc])(pDevExt,pIrp);
	KdPrint(("HelloWdmPnp leave..."));
	return status;

}

#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(
    IN OUT PDRIVER_OBJECT   DriverObject,
    IN PUNICODE_STRING      RegistryPath
    )
{
 
	KdPrint(("DriverEntry enter...."));


	DriverObject->DriverExtension->AddDevice = HelloWdmAddDevice;
	DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWdmPnp;

    
	DriverObject->MajorFunction[IRP_MJ_CREATE] =
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = HELLOWDM_DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HELLOWDM_DispatchDeviceControl;
    DriverObject->DriverUnload = HELLOWDM_DriverUnload;

	KdPrint(("DriverEntry leave...."));

    return STATUS_SUCCESS;
}
#ifdef __cplusplus
}; // extern "C"
#endif

INF文件:
;--------- Version Section ---------------------------------------------------

[Version]
Signature="$CHICAGO$";
Provider=WorldWang_Device
DriverVer=11/1/2007,3.0.0.3

; If device fits one of the standard classes, use the name and GUID here,
; otherwise create your own device class and GUID as this example shows.

Class=WorldWangDevice
ClassGUID={F8F8064C-EE05-41ea-99D5-55365AB81718}


;--------- SourceDiskNames and SourceDiskFiles Section -----------------------

; These sections identify source disks and files for installation. They are
; shown here as an example, but commented out.

[SourceDisksNames]
1 = "HelloWdm",Disk1,,

[SourceDisksFiles]
HelloWdm.sys = 1, ,

;--------- ClassInstall/ClassInstall32 Section -------------------------------

; Not necessary if using a standard class

; 9X Style
[ClassInstall]
Addreg=Class_AddReg

; NT Style
[ClassInstall32]
Addreg=Class_AddReg

[Class_AddReg]
HKR,,,,%DeviceClassName%
HKR,,Icon,,"-5"

;--------- DestinationDirs Section -------------------------------------------

[DestinationDirs]
YouMark_Files_Driver = 10,System32\Drivers

;--------- Manufacturer and Models Sections ----------------------------------

[Manufacturer]
%MfgName%=Mfg0

[Mfg0]

; PCI hardware Ids use the form
; PCI\VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd
;PCI\VEN_9999&DEV_9999
;PCI\VEN_8086&DEV_7111
;修改要挂载的设备的vendorId和productID
%DeviceDesc%=YouMark_DDI, PCI\VEN_9999&DEV_9999

;---------- DDInstall Sections -----------------------------------------------
; --------- Windows 9X -----------------

; Experimentation has shown that DDInstall root names greater than 19 characters
; cause problems in Windows 98

[YouMark_DDI]
CopyFiles=YouMark_Files_Driver
AddReg=YouMark_9X_AddReg

[YouMark_9X_AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,HelloWdm.sys
HKR, "Parameters", "BreakOnEntry", 0x00010001, 0

; --------- Windows NT -----------------

[YouMark_DDI.NT]
CopyFiles=YouMark_Files_Driver
AddReg=YouMark_NT_AddReg

[YouMark_DDI.NT.Services]
Addservice = HelloWdm, 0x00000002, YouMark_AddService

[YouMark_AddService]
DisplayName = %SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\HelloWdm.sys

[YouMark_NT_AddReg]
HKLM, "System\CurrentControlSet\Services\HelloWdm\Parameters",\
"BreakOnEntry", 0x00010001, 0


; --------- Files (common) -------------

[YouMark_Files_Driver]
HelloWdm.sys

;--------- Strings Section ---------------------------------------------------

[Strings]
ProviderName="WorldWang."
MfgName="WorldWang Soft"
DeviceDesc="Hello World WDM!"
DeviceClassName="WorldWang_Device"
SvcDesc="WorldWang"


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值