• 关机程序 .


    OSVERSIONINFO   OsVersionInfo;       //包含操作系统版本信息的数据结构  
      OsVersionInfo.dwOSVersionInfoSize   =   sizeof(OSVERSIONINFO);  
      GetVersionEx(&OsVersionInfo);         //获取操作系统版本信息  
      if(OsVersionInfo.dwPlatformId   ==   VER_PLATFORM_WIN32_WINDOWS)  
      {  
      //Windows98,调用ExitWindowsEx()函数重新启动计算机  
      DWORD   dwReserved;  
      ExitWindowsEx(EWX_REBOOT,dwReserved);     //可以改变第一个参数,实现注销用户、    
                                                                                        //关机、关闭电源等操作  
      //   退出前的一些处理程序  
      }  
    ===============================================================

    From   MSDN  
      Windows   NT:   The   calling   process   must   have   the   SE_SHUTDOWN_NAME   privilege.   For   more   information,   see   the   following   Remarks   section.    
       
      From   remark  
      Windows   NT:   To   shut   down   or   restart   the   system,   the   calling   process   must   use   theAdjustTokenPrivileges   function   to   enable   the   SE_SHUTDOWN_NAME   privilege.   For   more   information   about   security   privileges,   seePrivileges.    
       
      it   means    
       
      void   CShutdownDlg::OnButton1()    
      {  
      HANDLE   hdl;      
      OpenProcessToken(GetCurrentProcess(),   TOKEN_ADJUST_PRIVILEGES,   &hdl);      
        PTOKEN_PRIVILEGES   ptoken   =   (PTOKEN_PRIVILEGES)   new   BYTE[sizeof(DWORD)   +      
      sizeof(LUID_AND_ATTRIBUTES)];      
      ptoken->PrivilegeCount   =   1;      
      LUID   uid;      
      LookupPrivilegeValue(NULL,   SE_SHUTDOWN_NAME,   &uid);      
       
      ptoken->Privileges[0].Luid   =   uid;      
      ptoken->Privileges[0].Attributes   =   SE_PRIVILEGE_ENABLED;      
      AdjustTokenPrivileges(hdl,   FALSE,   ptoken,   0,   NULL,   NULL);         //向进程表内写入数据  
        CloseHandle(hdl);      
      delete   [](BYTE   *)ptoken;      
      ExitWindowsEx(EWX_FORCE|EWX_POWEROFF,0);  
      }  
    =================================================================================================================

    Window关机函数ExitWindowsEx详解

    “系统ShutDown”属于Windows系统的一种基本服务。功能上有“关闭系统”,“注销用户”,“锁定工作站”3中操作。SDK中提供了几个函数,来对此服务进行调用。

    “关闭系统”功能使计算机可以被安全的关闭。所有在文件系统里缓冲的内容都被强制写入磁盘。然后,显示相应的对话框,提示用户计算机将被关闭或者已经准备好被关闭。可选的情况一般是计算机在关闭后重起,而不是直接切断电源。

    如果一个进程调用“注销”功能函数,则该进程所在的安全环境范围内的所有进程都被终止,使当前的用户退出系统。一个登陆对话框被显示,期待新用户的登陆。

    “锁定工作站”功能使你可以在离开计算机的时候,保护计算机屏幕不被未授权的用户看到。要解除锁定,必须用管理员或着授权用户的帐号和密码重新登陆。

    如何关闭系统:

    程序可以用两种方式关闭本地或远程计算机
    直接关闭系统
    关闭系统并重启
    Windows NT/2000 及后续版本: 程序必须拥有SE_SHUTDOWN_NAME权限才能成功调用关闭函数。


    ExitWindowsEx函数可以用来关闭系统。如函数成功调用,系统对每个窗口发送WM_QUERYENDSESSION 消息,询问窗口所属的程序是否可以被终止。收到此消息的程序应该进行响应,清除环境释放资源,然后返回TRUE表示自己可以被终止。然而调用ExitWindowEx的时候如果指定了EXW_FORCE,则系统强行终止相关的进程并关闭,这样可能导致数据的丢失。

    这是一段在NT/2000中调用ExitWindowEx关闭系统的程序(强制关闭所有程序)。

    在windows95/98/me中直接调用ExitWindowEx即可。
    -----------------------------------------------------------------------------------------------------------


    HANDLE hToken;
    TOKEN_PRIVILEGES tkp;

    // Get a token for this process.

    if (!OpenProcessToken(GetCurrentProcess(),

    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))


    Error("OpenProcessToken");

    // Get the LUID for the shutdown privilege.

    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
    &tkp.Privileges[0].Luid);

    tkp.PrivilegeCount = 1; // one privilege to set

    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    // Get the shutdown privilege for this process.

    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,

    (PTOKEN_PRIVILEGES)NULL, 0);

    // Cannot test the return value of AdjustTokenPrivileges.

    if (GetLastError() != ERROR_SUCCESS)

    error("AdjustTokenPrivileges");

    // Shut down the system and force all applications to close.

    if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0))

    error("ExitWindowsEx");

    -----------------------------------------------------------------------------------------------------------

    Windows NT/2000以及后续版本:

    InitiateSystemShutdown函数可以指定一段延时,在进行延时计数的时候,在将被关闭的目标计算机上显示一个对话框,提示用户尽快注销。一旦计数结束,系统则立刻被关闭。在此之前,可以调用AbortSystemShutdown函数停止计数,取消相应的关闭操作。InitiateSystemShutdown也可以指定让系统重启。


    InitiateSystemShutdown有一个参数LPTSTR lpMachineName,可以指定为网络上的计算机名字,也就是说,可以关闭网络上的他计算机(如果你的用户在该计算机上有足够的权限的话)。


    以下这个例子调用InitiateSystemShutdown函数关闭用户已经登陆的本地计算机(要关闭远程计算机将InitSystemShutdown第一个参数由NULL改为正确的计算机名字或)。同样的,也需要先获得SE_SHUTDOWN_NAME权限。


    ---------------------------------------------------------------------------------------------------------

    HANDLE hToken; // handle to process token

    TOKEN_PRIVILEGES tkp; // pointer to token structure

    BOOL fResult; // system shutdown flag

    // Get the current process token handle so we can get shutdown

    // privilege.

    if (!OpenProcessToken(GetCurrentProcess(),

    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))

    ErrorHandler("OpenProcessToken failed.");

    // Get the LUID for shutdown privilege.

    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
    &tkp.Privileges[0].Luid);

    tkp.PrivilegeCount = 1; // one privilege to set

    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    // Get shutdown privilege for this process.

    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,

    (PTOKEN_PRIVILEGES) NULL, 0);

    // Cannot test the return value of AdjustTokenPrivileges.

    if (GetLastError() != ERROR_SUCCESS)

    ErrorHandler("AdjustTokenPrivileges enable failed.");

    // Display the shutdown dialog box and start the time-out countdown.

    fResult = InitiateSystemShutdown( NULL, // shut down local computer

    "Click on the main window and press \

    the Escape key to cancel shutdown.", // message to user

    20, // time-out period

    FALSE, // ask user to close apps

    TRUE); // reboot after shutdown


    if (!fResult)


    {

    ErrorHandler("InitiateSystemShutdown failed.");

    }
    // Disable shutdown privilege.


    tkp.Privileges[0].Attributes = 0;


    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,


    (PTOKEN_PRIVILEGES) NULL, 0);


    if (GetLastError() != ERROR_SUCCESS)


    {

    ErrorHandler("AdjustTokenPrivileges disable failed.");

    }

    ---------------------------------------------------------------------------------------------
    而使用AbortSystemShutoown取消InitialSystemShutdown操作的代码如下(记住要在延时结束前执行才能起作用


    // Get the current process token handle so we can get shutdown

    // privilege.


    if (!OpenProcessToken(GetCurrentProcess(),

    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))

    {

    ErrorHandler("OpenProcessToken failed.");

    }


    // Get the LUID for shutdown privilege.


    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,

    &tkp.Privileges[0].Luid);


    tkp.PrivilegeCount = 1; // one privilege to set


    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;


    // Get shutdown privilege for this process.


    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,

    (PTOKEN_PRIVILEGES)NULL, 0);


    // Cannot test the return value of AdjustTokenPrivileges.


    if (GetLastError() != ERROR_SUCCESS)


    {

    ErrorHandler("AdjustTokenPrivileges enable failed.");

    }

    // Prevent the system from shutting down.

    fResult = AbortSystemShutdown(NULL);

    if (!fResult)

    {

    ErrorHandler("AbortSystemShutdown failed.");

    }

    // Disable shutdown privilege.

    tkp.Privileges[0].Attributes = 0;

    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,

    (PTOKEN_PRIVILEGES) NULL, 0);

    if (GetLastError() != ERROR_SUCCESS)

    {

    ErrorHandler("AdjustTokenPrivileges disable failed.");

    }

    break;

    关于用户权限(Privileges)的详细信息,可以参见MSDN

    如何注销当前用户


    可以使用ExitWindows或ExitWindowsEx函数注销当前用户。

    在默认的情况下,当程序调用ExitWindows或ExitWindowsEx注销的时候,WM_QUERYENDSESSION消息也被发送到系统内的每个窗口。窗口所属的程序响应此消息并且返回TRUE表示可以被关闭,如果任意一个程序返回FALSE,注销操作将被取消。

    Windows NT/2000以及后续版本:

    当一个程序响应WM_QUERYENDSESSION并返回TRUE,那么它就会立刻接受到WM_ENDSESSION消息并马上结束,而不管其他的程序是怎么样回应WM_QUERYENDSESSION消息的。

    Windows 95/98/Me:只有当系统内所有的程序都对WM_QUERYENDSESSION消息回应TRUE之后,他们才会一起接受到WM_ENDSESSION 消息,然后结束。

    如果要强制关闭所有的程序,使用ExitWindowsEx函数,指定EXW_FORCE标志。如果这样做,系统不发送WM_QUERYENDSESSION 消息,而直接终止正在运行的程序。

    在注销的时候,系统还向每一个进程发送CTRL_LOGOFF_EVENT 控制码。控制台程序可以注册一个HandlerRoutine例程来处理这个控制码(使用SetConsoleCtrlHandler函数)。(更多的关于控制台的控制码,参见MSDN里“HandlerRoutine”有关章节)

    综上所述:只有所有的程序都允许退出,注销操作才能成功。如果某一个程序响应WM_QUERYENDSESSION并返回FALSE ,用户则不能被注销。这样就可以写出防止用户注销或关闭的程序(非强制情况)。

    //这是注销当前用户的代码

    ExitWindows(0, 0);

    //响应WM_QUERYENDSESSION消息,如果在弹出消息框里选择NO,则取消注销。

    case WM_QUERYENDSESSION:

    {

    int r;

    r = MessageBox(NULL, "Shut down?","WM_QUERYENDSESSION", MB_YESNO);

    // Return TRUE to allow shutdown, FALSE to stop.

    return r == IDYES;

    break;

    }

    如何锁定工作站

    使用LockWorkStation函数即可锁定工作站。系统会显示一个锁定对话框,告诉用户此工作站正在使用并且已经被锁定,可以被执行锁定的用户或管理员解锁,解锁的方式是按下CTRL_ALT_DEL并用正确的帐号和密码登陆。

    LockWorkStation函数成功调用的条件是:

    调用者必须是运行在系统交互桌面上的一般进程。

    必须已经有用户登陆到系统

    工作站未被锁定。

    拥有正常窗口和消息队列的程序通过WM_QUERYENDSESSION或WM_ENDSESSION消息获得关闭通知。

    控制台则是在其控制流程(Handle Routines)里接受关闭通知。要注册一个控制台控制流程,应该使用SetConsoleCtrlHandler函数

    服务程序在其控制流程里接受退出通知。要注册一个服务控制流程,应该使用RegisterServiceCtrlHandlerEx函数。

    关闭系统函数列表

    函数名                函数功能描述

    AbortSystemShutdown          取消由InitSystemShutdown引起的系统关闭操作

    ExitWindows              注销当前用户

    ExitWindowsEx             注销用户,关闭计算机,关闭计算机并且重启

    InitiateSystemShutdown         发起关闭系统操作,可以选择关闭后重启

    InitiateSystemShutdownEx        同InitiateSystemShutdown,扩展的功能是可以在系统
                        事件日志(事件号6006)中写入一个用户指定的双字节码

    LockWorkStation            锁定工作站


    系统关闭消息

    WM_ENDSESSION

    wParam

    表示是否要终止程序。如果是TRUE,指令该程序终止,否则是FALSE

    lParam

    表示用户注销还是系统被关闭。如果此参数包含ENDSESSION_LOGOFF(lParam在这里是按位取值的)位,则表示是用户注销

    Windows 2000 以及后续版本:如果lParam ==0,则表示系统被关闭。

    程序收到此消息,如果wParam为TRUE,在完成消息处理后,程序随时都有可能被关闭。所以在此消息的处理过程里,应该尽量完成程序销毁前所需要进行的工作。

    WM_QUERYENDSESSION

    wParam

    保留,未使用

    lParam

    同WM_ENDSESSION;

    DefWindowProc默认返回:TRUE

    ps

    1.HANDLE hToken;
    2.TOKEN_PRIVILEGES tkp;
    3.
    4.if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) {
    5. AfxMessageBox("无法打开存取命令");
    6.}
    7.
    8.LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
    9.
    10.tkp.PrivilegeCount=1;
    11.tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    12.
    13.AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);
    14.
    15.
    16.if(GetLastError()!=ERROR_SUCCESS) {
    17. AfxMessageBox("无法关机");
    18.}
    19.//以上是取得当前用户的Token后,利用这个Token来取得权限才可以执行关机操作
    20.
    21.//关机函数
    22.if(!ExitWindowsEx(EWX_POWEROFF|EWX_FORCE,0)) {
    23. AfxMessageBox("无法关机");
    24.}

  • 相关阅读:
    【区间DP&&记忆化搜索】乘法游戏
    洛谷P1608路径统计
    2021省选游记
    涂色计划P4170
    01迷宫及路径记录(DFS&&BFS)
    [YBTOJ递推算法强化训练4]序列个数
    C++关于string 的优先队列以及重载运算符
    浅谈C++STL容器
    集合的划分
    图的表示
  • 原文地址:https://www.cnblogs.com/zhoug2020/p/2430099.html
Copyright © 2020-2023  润新知