1、关机原理
   我们执行关机操作后,通常看到的是系统的关机画面,然后是或短或长的等待,究竟这个关机画面后隐藏怎么样的过程呢?关机其实和开机一样涉及到多个过程,是多个进程,组件之间一个相互协作的过程,下面我们来细致了解一下:
   1)发起关机指令
    当用户发起关机指令时,将调起关机程序,windows xp下是shutdowm.exe,win98和win2000是rundll32.exe,该程序会通知windows子系统进程csrss.exe,CSRSS.EXE收到通知以后会和Winlogon.EXE做一个数据交换,做好关机的准备工作,接着由Winlogon.EXE通知CSRSS.EXE开始关闭系统的流程。
    csrss.exe是客户端服务子系统,用以控制windows图形相关子系统;
    winlogon.exe则是windows NT用户登录程序,主要管理用户登录和退出。
   2)通知用户进程退出
    第一个过程中windows子系统进程csrss.exe收到winlogon.exe的通知后,会依次查询拥有顶层窗口的用户进程,如常见的用户程序,杀毒软件,防火墙等,让这些进程退出。如果某一个用户进程在一个默认的超时时间5000毫秒(可以通过修改注册表键值HKEY_CURRENT_USER\Control Panel\Desktop\ HungAppTimeout设定超时时间)内没有退出的话,Windows会显示一个结束任务对话框用于询问用户是否结束这个任务。默认情况下将显示这个对话框并一直保持而不会自动关闭。对于控制台程序来说,基本情况类似,只不过Windows使用HKEY_CURRENT_USER\Control Panel\Desktop\ WaitToKillAppTimeout值来设置超时时间。
   3)关闭系统进程
    在关闭用户进程后,开始进入到关闭系统进程阶段,正常使用状态下无法结束的系统进程,如smss.exe,lsass.exe等将被终止。终止系统进程和终止用户进程略有不同,windows在终止系统进程的时候并不像终止用户进程那样,如果无法在规定时间内种植提示用户,则直接跳过这个进程,去执行下一个系统进程的终止操作。其中使用的超时时间和第2步使用的时间相同。

   以上三点,被成为关机过程中的软保护,这样对于操作系统或第三方应用程序都能起到保护作用,如果强行关闭可能导致相关文件破坏等异常。

   4)核心组件的退出和最后的关机工作
    这一步被成为关机硬保护,winlogon.exe调用系统API函数NtShutdownSystem()或ZwShutdownSystem函数来命令系统执行windows核心组件的退出和最后的关机工作。例如:设备驱动在这个阶段里面完成一些驱动设定的特殊操作;也是在这个阶段,配置管理系统将被修改过的注册表数据会写道磁盘里面。等除了电源管理以后的全部子系统完成退出以后,电源管理完成最后的操作,如重启、关机等。

2、响应关机事件分析
    不管是直接按机箱上的Power按钮,还是点击开始菜单->关闭计算机(注销、关机、重启),我们的应用程序都可以响应这类事件,那就是窗口消息WM_QUERYENDSESSION和WM_ENDSESSION。
    系统提供了一个常用的API实现系统的注销、关机和重启,它的声明为:
    BOOL ExitWindowsEx(
         UINT uFlags,
        DWORD dwReason
        );
    参数uFlags可分为两类,之间可以用“|”合并:
    1). 关闭动作,有以下标志:EWX_LOGOFF(注销)、EWX_SHUTDOWN(关闭系统后不切断电源,即使主板支持ATX电源管理)、EWX_POWEROFF(关机,关闭系统后切断电源,需主板支持)、EWX_REBOOT(重启)。
    2). 关闭强度,有以下标志:数值0(安全关闭,不使用该类标志时默认为该项)、EWX_FORCEIFHUNG(应用程序挂起一段时间后强行关闭)、EWX_FORCE(强行关闭,不管应用程序有没有挂起)。
    如果不使用关闭强度标志(EWX_FORCE或EWX_FORCEIFHUNG),关机是安全的,也就是说,在关机的软保护时,系统将给每个以桌面为顶级的窗口进程发送WM_QUERYENDSESSION消息。如果超过5000毫秒(可以通过修改注册表键值HKEY_CURRENT_USER\Cont rol Panel\Desktop\ HungAppTimeout设定超时时间)仍未有WM_QUERYENDSESSION消息的返回,则弹出结束任务对话框用于询问用户是否结束这个任务。默认情况下将显示这个对话框并一直保持而不会自动关闭;如果设置了自动结束任务(HKEY_CURRENT_USER\Cont rol Panel\Desktop\AutoEndTasks键值改为1),那么超时(HungAppTimeout)后仍未有 WM_QUERYENDSESSION消息的返回值时,不再显示结束任务对话框而直接结束这个挂起的任务。如果多个进程响应了 WM_QUERYENDSESSION并挂起(如记事本弹出询问是否保存的消息框),那么系统对于每个进程是串行处理的,即等待第一个挂起的进程响应 WM_QUERYENDSESSION并返回后(立即发送WM_ENDSESSION通知同一窗口用户的选择<是否确认关闭>),再给下一个进程发送WM_QUERYENDSESSION并等待挂起超时。

4、如何快速关机
   通过前面关机过程的描述,我们可以知道关机过程是经过一个一个阶段逐步完成,某一步出错都有可能导致关机失败,前3个步骤时关机过程中最耗时间的一段,常见的关机问题都是由这3个步骤引起。
   经常听到快速关机,或者是关机优化软件,那么它们到底怎么是实现的,有没有用呢?
   1)在关机原理里提到两个注册表键值,对应相关程序的超时响应时间,我们可以修改减小这两个键值,HKEY_CURRENT_USER\Control Panel\Desktop\ HungAppTimeout和HKEY_CURRENT_USER\Control Panel\Desktop\ WaitToKillAppTimeout,这确实是有效的,如前面所述,原因在于前一键值设定的是用户进程自动退出的超时时间,后一键值设定的是控制台程序自动退出的超时时间。减小这两个键值会加快用户和控制台进程的退出速度,从而加快关机速度。
   2)经典的关机技巧
    用ctrl健配合任务管理器快速关机,即可在一两秒内立即断电关机,实际上原理是这个关机过程跳过了前三个步骤,直接进入第4步,这样带来的风险就是您的应用程序数据可能丢失,操作系统文件也可能被破坏进不了系统。那些所谓的快速关机软件,就是这样直接调用ntdll.dll中的ZwShutdownSystem()实现的。实际上,正常来说,windows关机速度变慢的多数问题在于关机前用户使用的程序过多,或者是执行关机前没有退出一些大型的软件,或者一些软件自身的退出管理存在问题,从而造成了关机的延迟,因此加快关机速度,正确的做法是减少应用程序对关机过程的影响,如在关机前尽量关闭用户程序,尽量不要再电脑处于忙的状态时关机。
    我们来了解下实现断电关机的代码:
    const int SE_SHUTDOWN_PRIVILEGE = 0x13;
    typedef int (__stdcall *PFN_RtlAdjustPrivilege)( INT, BOOL, BOOL, INT*);
    typedef int (__stdcall *PFN_ZwShutdownSystem)(INT);
    HMODULE hModule = ::LoadLibrary(_T("ntdll.dll"));
    if( hModule != NULL)
    {
        PFN_RtlAdjustPrivilege pfnRtl = (PFN_RtlAdjustPrivilege)GetProcAddress( hModule, "RtlAdjustPrivilege");
        PFN_ZwShutdownSystem pfnShutdown = (PFN_ZwShutdownSystem)GetProcAddress( hModule,"ZwShutdownSystem");
        if( pfnRtl != NULL &pfnShutdown != NULL )
        {
            int en = 0;
            int nRet= pfnRtl( SE_SHUTDOWN_PRIVILEGE, TRUE, TRUE, &en);
            if( nRet == 0x0C000007C )
            nRet = pfnRtl(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &en);
            //SH_SHUTDOWN = 0;
            //SH_RESTART = 1;
            //SH_POWEROFF = 2;
            const int SH_POWEROFF = 2;
            nRet = pfnShutdown(POWEROFF);
        }

    }

3、无法关机调试实例

  http://blogs.msdn.com/ntdebugging/archive/2009/11/09/system-won-t-power-down.aspx

  这篇文章详介绍了关机原理,和一个系统无法关机的调试实例,调试过程很值得学习。