注册IRP_MJ_SHUTDOWN事件 基于ReactOS0303

系统关闭时,会向注册SHUTDOWN事件的设备驱动发送IRP_MJ_SHUTDOWN事件。

NTSTATUS STDCALL
NtShutdownSystem(IN SHUTDOWN_ACTION Action)
{
    if (Action > ShutdownPowerOff)
     return STATUS_INVALID_PARAMETER;
   Status = PsCreateSystemThread(&ThreadHandle,
                                 THREAD_ALL_ACCESS,
                                 NULL,
                                 NULL,
                                 NULL,
                                 ShutdownThreadMain,
                                 (PVOID)Action);
}

VOID STDCALL
ShutdownThreadMain(PVOID Context)
{
    IoShutdownRegisteredDevices();
}

VOID
NTAPI
IoShutdownRegisteredDevices(VOID)
{
    ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
                                            &ShutdownListLock);
    while (ListEntry)
    {
        /* Get the shutdown entry */
        ShutdownEntry = CONTAINING_RECORD(ListEntry,
                                          SHUTDOWN_ENTRY,
                                          ShutdownList);

        /* Get the attached device */
        DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);

        /* Build the shutdown IRP and call the driver */
        Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
                                           DeviceObject,
                                           NULL,
                                           0,
                                           NULL,
                                           &Event,
                                           &StatusBlock);
        Status = IoCallDriver(DeviceObject, Irp);
        if (Status == STATUS_PENDING)
        {
            /* Wait on the driver */
            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
        }

        /* Free the shutdown entry and reset the event */
        ExFreePool(ShutdownEntry);
        KeClearEvent(&Event);

        /* Go to the next entry */
        ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
                                                &ShutdownListLock);
     }
}

调用Native API NtShutdownSystem时会遍历ShutdownListHead队列,取出每个元素,这个元素的结构中包含设备对象:

typedef struct _SHUTDOWN_ENTRY
{
    LIST_ENTRY ShutdownList;
    PDEVICE_OBJECT DeviceObject;
} SHUTDOWN_ENTRY, *PSHUTDOWN_ENTRY;

之后获得这个设备的设备栈深度并以此建立一个类型为IRP_MJ_SHUTDOWN的IRP请求包,以同步的方式发向设备栈的最上层设备。 设备栈中的设备驱动如果注册了IRP_MJ_SHUTDOWN事件那就调用相应的回调,如果没有注册就按默认的方式完成请求或者下发请求。

联系驱动程序注册IRP_MJ_SHUTDOWN事件和IoShutdownRegisteredDevices函数的是IoRegisterShutdownNotification---注册关机通知函数。这个函数新建SHUTDOWN_ENTRY结构,并填入设备对象,然后把SHUTDOWN_ENTRY结构挂入ShutdownListHead队列。

/*
 * @implemented
 */
NTSTATUS
NTAPI
IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
{
    PSHUTDOWN_ENTRY Entry;

    /* Allocate the shutdown entry */
    Entry = ExAllocatePoolWithTag(NonPagedPool,
                                  sizeof(SHUTDOWN_ENTRY),
                                  TAG_SHUTDOWN_ENTRY);
    if (!Entry) return STATUS_INSUFFICIENT_RESOURCES;

    Entry->DeviceObject = DeviceObject;

    /* Insert it into the list */
    ExInterlockedInsertHeadList(&ShutdownListHead,
                                &Entry->ShutdownList,
                                &ShutdownListLock);

    DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED;
    return STATUS_SUCCESS;
}

驱动入口以如下的方式注册关闭通知:

DriverEntry(pDriverObject,pRegistryPath)
{
    pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Shutdown;
    IoRegisterShutdownNotification(pDriverObject);
}
时间: 2024-08-27 13:10:05

注册IRP_MJ_SHUTDOWN事件 基于ReactOS0303的相关文章

jquery为链接a元素注册click事件并避免跳转现象

jquery为链接a元素注册click事件并避免跳转现象:在实际应用中,可能需要将链接a作为一个普通的按钮使用,但是由于点击按钮会导致跳转动作,下面就通过代码实例介绍一下如何实现点击功能,并且不会出现跳转现象,代码如下: <!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta name="author" content="http://www.

Android RecyclerView单击、长按事件:基于OnItemTouchListener +GestureDetector标准实现(二),封装抽取成通用工具类

?? Android RecyclerView单击.长按事件:基于OnItemTouchListener +GestureDetector标准实现(二),封装抽取成通用工具类 我写的附录文章2,介绍了Android如何基于OnItemTouchListener +GestureDetector实现单击.长按事件的监听,由于如今RecyclerView在Android开发是如此的普遍,以及RecyclerView的单击事件是如此的常用,如果像附录文章2那样把一堆事件监听写到业务逻辑代码里面,那得写

手机的touch事件(基于jquery)

javascript代码: $.swipe=function(opt){  var o = $.extend({    mainSelector:"",    swipeLeft:function(e,v){},    swipeRight:function(e,v){},    swipeEnds:function(v,e){}}, opt || {});  var startX=0,startY=0;var obj={    touchStart: function (e){   

菜鸟学JS(四)——javascript为按钮注册回车事件(设置默认按钮)

不得不说,在JS方面,自己真的是个不折不扣的菜鸟.对于JS以及一些JS框架如JQuery等JS框架,自己也只是处在简单应用的阶段,当然自己也在不断的学习当中,希望将来能跟大家分享更多JS方面的心得.今天先来点开胃的,说一下如何设置一个默认按钮,就是不管焦点在不在按钮上,只要按下回车,就等于触发了按钮的单击事件. 代码非常简单,要完成这个功能,只需几行代码: //为keyListener方法注册按键事件 document.onkeydown=keyListener; function keyLis

关于在Cocos2dx中注册触摸事件——Lua

关于在Cocos2dx中注册触摸事件,之前一直对此一知半解,这两天在看引擎的源码,趁此机会写下来... 以下纯属个人理解,如有不对欢迎指正... 在引擎的CCLayer类中声明了有四个方法: 1 virtual bool onTouchBegan(Touch *touch, Event *unused_event); 2 virtual void onTouchMoved(Touch *touch, Event *unused_event); 3 virtual void onTouchEnde

使用for循环批量注册的事件不能正确获取索引值

使用for循环批量注册的事件不能正确获取索引值:可能不少朋友会遇到一个问题,那就是当使用for循环批量注册事件处理函数,然后最后通过事件处理函数获取当前元素的索引值的时候会失败,先看一段代码实例: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset=" utf-8"> 5 <meta name="author" content="http://www.

人禾娱乐绿色VIP注册通道之基于 Lerna 管理 packages 的 Monorepo

人禾娱乐绿色VIP注册通道之基于 Lerna 管理 packages 的 Monorepo对于维护过多个package的同学来说,都会遇到一个选择题,这些package是放在一个仓库里维护还是放在多个仓库里单独维护,本文通过一个示例讲述了如何基于Lerna管理多个package,并和其它工具整合,打造高效.完美的工作流,最终形成一个最佳实践 背景 最近在工作中接触到一个项目,这个项目是维护一套 CLI,发到 npm 上供开发者使用.先看一张图: 项目仓库中的根目录上就三个子模块的文件夹,分别对应

11. Dubbo原理解析-注册中心之基于dubbo协议的接口介绍

服务注册与发现的中心,服务的提供者将服务发布到注册中心,服务的使用着到注册中引用服务. Dubbo的注册中心提供了多种实现,其实现是基于dubbo的spi的扩展机制的,使用着可以直接实现自己的注册中心. @SPI("dubbo") public interface RegistryFactory { /** * 连接注册中心. * 连接注册中心需处理契约 * 1. 当设置check=false时表示不检查连接,否则在连接不上时抛出异常. * 2. 支持URL上的username:pas

12. Dubbo原理解析-注册中心之基于dubbo协议的简单注册中心实现

基于dubbo协议开源只是给出了默认一个注册中心实现SimpleRegistryService, 它只是一个简单实现,不支持集群,就是利用Map<String/*ip:port*/, Map<String/*service*/, URL>来存储服务地址, 具体不在啰嗦了,请读者翻看源代码,可作为自定义注册中的参考. 注册中心启动 SimpleRegistryService本身也是作为一个dubbo服务暴露. <dubbo:protocolport="9090"