IoRegisterPlugPlayNotification源码分析

原创 2016年08月30日 22:24:22

    IoRegisterPlugPlayNotification函数的作用是为指定guid的设备注册一个回调函数,当进入设备驱动并调用IoSetDeviceInterfaceState使能设备访问接口后,让系统调用之前注册的回调函数,以实现通知的目的.wrk1.2源码中并没有IO管理器的实现,因此,只能退而求其次,参考ReactOS中关于IoRegisterPlugPlayNotification的实现.

    ReactOS在系统初始化阶段调用PoInitSystem初始化电源管理器时,会以

        IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
                                       0, /* The registry has not been initialized yet */
                                       (PVOID)&GUID_DEVICE_SYS_BUTTON,
                                       IopRootDeviceNode->
                                       PhysicalDeviceObject->DriverObject,
                                       PopAddRemoveSysCapsCallback,
                                       NULL,
                                       &NotificationEntry);
的形式为集成在主板按键上的调用IoRegisterPlugPlayNotification.

    参数1 EventCategoryDeviceInterfaceChange表明Pnp管理器在接到设备接口状态变化(Enable/Disable)时调用先前注册的回调函数;

    参数3 GUID_DEVICE_SYS_BUTTON是指被IoSetDeviceInterfaceState操作的接口;

    参数5和6是回调函数的入口地址和参数;

    不得不说,系统中注册回调函数都有一定的相似性,步骤可归纳为2步:1).为一个Entry分配pool内存,并用回调函数入口地址和参数Context初始化Entry,并初始化其他域(如回调条件);2).将刚分配的Entry结构以互斥的方式加入到内核中相应的队列中.IoRegisterPlugPlayNotification也是如此:

{
//分配池内存
Entry = ExAllocatePoolWithTag(
		NonPagedPool,
		sizeof(PNP_NOTIFY_ENTRY),
		TAG_PNP_NOTIFY);
//从interface获得设备的名字
Status = IoGetDeviceInterfaces(
			(LPGUID)EventCategoryData,
			NULL, /* PhysicalDeviceObject OPTIONAL */
			0, /* Flags */
			&SymbolicLinkList);
NotificationInfos.Version = 1;//以下是初始化Entry结构
NotificationInfos.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION);
RtlCopyMemory(&NotificationInfos.Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID));
RtlCopyMemory(&NotificationInfos.InterfaceClassGuid, EventCategoryData, sizeof(GUID));


Entry->PnpNotificationProc = CallbackRoutine;
	Entry->EventCategory = EventCategory;
	Entry->Context = Context;
//最后,获得互斥锁,并插入PnpNotifyListHead
KeAcquireGuardedMutex(&PnpNotifyListLock);
InsertHeadList(&PnpNotifyListHead,
		&Entry->PnpNotifyList);
KeReleaseGuardedMutex(&PnpNotifyListLock);
}
    回调函数注册后,将在什么情况下才会被调用?通过搜索对PnpNotifyListHead的引用,可以发现端倪:

Pnpnotify.c!IopNotifyPlugPlayNotification中遍历PnpNotifyListHead:
	ListEntry = PnpNotifyListHead.Flink;
	while (ListEntry != &PnpNotifyListHead)
	{
		ChangeEntry = CONTAINING_RECORD(ListEntry, PNP_NOTIFY_ENTRY, 
PnpNotifyList);
		ListEntry = ListEntry->Flink;
	}
这是典型的遍历队列操作啊,有必要介绍一下IopNotifyPlugPlayNotification的流程:

一般IoSetDeviceInterfaceState会以下列方式调用IopNotifyPlugPlayNotification

    EventGuid = Enable ? &GUID_DEVICE_INTERFACE_ARRIVAL : &GUID_DEVICE_INTERFACE_REMOVAL;
    IopNotifyPlugPlayNotification(
        PhysicalDeviceObject,
        EventCategoryDeviceInterfaceChange,
        EventGuid,
        &GuidString,
        (PVOID)SymbolicLinkName);
    当IopNotifyPlugPlayNotification被调用时,它搜索PnpNotifyListHead链表,逐项比对已注册在PnpNotifyListHead队列中的PNP_NOTIFY_ENTRY各项,如果PNP_NOTIFY_ENTRY中接口GUID和产生设备插拔事件的接口GUID相同,则调用PNP_NOTIFY_ENTRY中的回调函数,去完成一些挂起的IRP请求.


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

mjpg-streamer项目源码分析

前一段时间自己买了个开发板(GT2440的),可是我没有够相应的买cmos摄像头,可是又想做下国嵌的usb视频采集和传输的哪个项目,没办法,只好网上找找相关的项目,最终发现了mjpg-streamer...

JAVA随笔篇一(Timer源码分析和scheduleAtFixedRate的使用)

写完了基础篇,想了很久要不要去写进阶篇,去写JSP等等的使用方法,最后决定先不去写,因为自己并不是JAVA方面的大牛,目前也在边做边学,所以决定先将自己不懂的拿出来学并记下来。 Timer是Java自...

Android MPAndroidChart使用教程和源码分析(四)

一.概述     MPAndroidChart是一款基于Android的开源图表库,MPAndroidChart不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,应用...

微信(WeChat)电脑端多开分析+源码

0x00 前言不知道大家有没有多个微信号,我反正有一两三个。现在电脑端微信使用频率也比较高,主要用于大文件传输,或者手机电脑文件互传等等,除了不能收红包和看朋友圈,貌似电脑端没其他毛病。哦,还有个毛病...
  • angelxf
  • angelxf
  • 2017年05月14日 16:07
  • 2321

Android开发者,必须知道的并且没有遇到的异常,附带简单的解决方案和异常过程、源码的分析从java层到Jni层

android.os.TransactionTooLargeException: data parcel size 709428 bytes Android开发者,必须知道的并且没有遇到的异常,附带简...
  • jspping
  • jspping
  • 2017年05月12日 14:37
  • 765

ffmpeg学习十一:封装音视频到同一个文件(muxing.c源码分析)

这一节学习怎么把音频流和视频按一定的格式封装成一个文件。ffmpeg所给的例子muxing.c很好的演示封装的过程,因此,这一节主要是学习muxing.c这个文件。 这个文件的路径为:doc/exa...

owncloud源码分析1--部分修改Demo

最近做了修改owncloud云盘的项目。 owncloud本身是一个私有云盘,用到本地目录,项目要求是存储到FTP后转存到FAST,所以需要修改很多相关的东西。 一、首先是进入文件列表时的选择根目录,...

java观察者模式&源码自带观察者模式分析

最近感觉工作中学不到太多东西,忙着要开始着手换工作,自己的学习也不太扎实,已经着手开始把以前落后的的东西补上,更新博客可能会渐渐变少,虽然该开始写,深感自己知识的浅薄,各方面理解都不太够,虽然很多博文...

hadoop学习之路(二)hadoop基本概念原理以及单词统计任务源码分析

在上一遍博文中,已经将hadoop集群环境搭建完毕。那么,接下来,笔者再根据安装过程中的一些名词对象进行解释,以及大致的运行原理。最后,再获取hadoop-example jar中的单词计数源码,进行...

elasticsearch源码分析之Transport(五)

一、基本介绍 1.1概念介绍 transport模块是es通信的基础模块,在elasticsearch中用的很广泛,比如集群node之间的通信、数据的传输、transport client方式的数...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IoRegisterPlugPlayNotification源码分析
举报原因:
原因补充:

(最多只允许输入30个字)