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

2019-07-14 00:38发布

电源事件相关的IRP包括 IRP_MJ_POWER和IRP_MN_QUERY_CAPABILITIES 此处关于IRP_MN_QUERY_CAPABILITIES的使用FDO通过向底层PDO请求此IRP,会得到 DEVICE_CAPABILITIES结构体数据,此结构体会指明驱动程序支持的电源特新。 驱动代码: /////////////////////////////////////////////////////////////////////////////// /// /// Copyright (c) 2014 - /// /// Original filename: HelloWdm.cpp /// Project : HelloWdm /// Date of creation : 2014-07-02 /// Author(s) : /// /// Purpose : /// /// Revisions: /// 0000 [2014-07-02] Initial revision. /// /////////////////////////////////////////////////////////////////////////////// // $Id$ #ifdef __cplusplus extern "C" { #endif #include #include #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 ",&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;iDeviceState[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;iDeviceState[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;iType; KdPrint(("ShowResources uTyep:%d ",uTyep)); switch (uTyep) { //物理资源 case CmResourceTypePort: case CmResourceTypeMemory: { KdPrint(("start:%8X%8.8lX Length: %X ",pListDesc->u.Port.Start.HighPart, pListDesc->u.Port.Start.HighPart,pListDesc->u.Port.Length)); } break; //中断 case CmResourceTypeInterrupt: { KdPrint(("Level:%X Vector:%X Affinity:%X ",pListDesc->u.Interrupt.Level, pListDesc->u.Interrupt.Vector,pListDesc->u.Interrupt.Affinity)); } break; //DMA case CmResourceTypeDma: { KdPrint(("Channel:%X,PORT:%X ",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) ",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,System32Drivers ;--------- Manufacturer and Models Sections ---------------------------------- [Manufacturer] %MfgName%=Mfg0 [Mfg0] ; PCI hardware Ids use the form ; PCIVEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd ;PCIVEN_9999&DEV_9999 ;PCIVEN_8086&DEV_7111 ;修改要挂载的设备的vendorId和productID %DeviceDesc%=YouMark_DDI, PCIVEN_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%System32DriversHelloWdm.sys [YouMark_NT_AddReg] HKLM, "SystemCurrentControlSetServicesHelloWdmParameters", "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"