65.9K
CodeProject 正在变化。 阅读更多。
Home

中止系统关机

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.94/5 (6投票s)

2005年6月6日

1分钟阅读

viewsIcon

81871

downloadIcon

1427

停止已启动的系统关机,无需下载平台 SDK。

引言

AbortSystemShutdown 函数停止使用 InitiateSystemShutdown 函数启动的系统关机。InitiateSystemShutdown 函数启动指定计算机的关机和可选重启(见下图)。

System shutdown dialog

还有另一种方式可以收到此对话框(见下图):如果您的计算机感染了 Blaster 蠕虫或其变种,例如 W32.Blaster.Worm、W32.Blaster.C.Worm、W32.Blaster.B.Worm、W32.Randex.E (赛门铁克)、W32/Lovsan.worm (McAfee)、WORM_MSBLAST.A (趋势科技) 和 Win32.Posa.Worm (Computer Associates)。

System shutdown dialog

代码解释

AbortSystemShutdown 函数需要 Windows NT 3.1 或更高版本。因此,使用 Windows 版本要求宏很有用。您可以在此 文章中找到更多信息。

#define WinVerMajor()        LOBYTE(LOWORD(GetVersion()))

#define IsWinVerNTs()       (GetVersion() < 0x80000000)
#define IsWinVerNT351Plus() (IsWinVerNTs() && WinVerMajor() >= 3)

要停止本地计算机关机,调用进程必须具有 SE_SHUTDOWN_NAME 权限。这就是我们使用 AdjustTokenPrivileges 函数的原因。

此示例还说明了加载时动态链接。如果 DLL 不可用,则使用加载时动态链接的应用程序必须简单地终止。但是,运行时动态链接示例可以响应错误。

代码已为 UNICODE 准备就绪。如果您想创建 UNICODE 版本,请将 UNICODE 添加到预处理器定义中。

FormatMessage 函数可用于获取 GetLastError 返回的系统错误代码的错误消息字符串。

#include <windows.h>

#define WinVerMajor()  LOBYTE(LOWORD(GetVersion()))

#define IsWinVerNTs()  (GetVersion() < 0x80000000)
#define IsWinVerNT351Plus() (IsWinVerNTs() && WinVerMajor() >= 3)

#define ERR_MSG TEXT("This program requires Windows NT version 3.1 or later!")

BOOL (__stdcall * MyAbortSystemShutdown)(LPTSTR);

BOOL fAbortSystemShutdown(LPTSTR lpMachineName);
BOOL PreventSystemShutdown(void);

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, int nCmdShow)
{
    if (IsWinVerNT351Plus())
    {
        PreventSystemShutdown();
    }
    else
    {
        MessageBox(NULL, ERR_MSG, TEXT("Abort System Shutdown"), MB_OK);
    }

    return (0);
}

/*
 *    AbortSystemShutdown
 *
 *    The AbortSystemShutdown function stops a system shutdown started by using 
 *    the InitiateSystemShutdown function.
 */
BOOL fAbortSystemShutdown(LPTSTR lpMachineName)
{
    HINSTANCE hinstLib;
    BOOL result = FALSE;

    if (IsWinVerNT351Plus())
    {
        hinstLib = LoadLibrary(TEXT("Advapi32.dll"));

        if (hinstLib)
        {
            if (MyAbortSystemShutdown = (BOOL (__stdcall *)(LPTSTR)) 
                #ifdef UNICODE
                    GetProcAddress(hinstLib, "AbortSystemShutdownW"))  
                #else
                    GetProcAddress(hinstLib, "AbortSystemShutdownA"))
                #endif // !UNICODE
            {
                result = (MyAbortSystemShutdown)(lpMachineName);
            }
        }

        FreeLibrary(hinstLib);
    }

    return (result);
}

BOOL PreventSystemShutdown(void)
{
    HANDLE hToken;              // handle to process token 
    TOKEN_PRIVILEGES tkp;       // pointer to token structure 

    // Get the current process token
    // handle so we can get shutdown privilege.
    if (!OpenProcessToken(GetCurrentProcess(), 
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
    {
        return (FALSE);
    }

    // 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); 

    if (GetLastError() != ERROR_SUCCESS)
    {
        return (FALSE);
    }

    // Prevent the system from shutting down. 
    if (! fAbortSystemShutdown(NULL)) 
    {
        LPVOID lpMsgBuf;

        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                      FORMAT_MESSAGE_FROM_SYSTEM | 
                      FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, GetLastError(),
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
            (LPTSTR) &lpMsgBuf, 0, NULL
        );

        // Display the string.
        MessageBox(NULL, (LPCTSTR) lpMsgBuf, TEXT("Error"), 
                   MB_OK | MB_ICONINFORMATION);

        // Free the buffer.
        LocalFree(lpMsgBuf);

        return (FALSE);
    }

    // Disable shutdown privilege. 
    tkp.Privileges[0].Attributes = 0; 
    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);

    return (TRUE);
}

您可以通过使用参数 -a 执行 Windows XP shutdown.exe 实用程序来获得相同的结果。您还可以使用 shutdown -s -t 60 -c "bye-bye" 命令来调用系统关机对话框。

© . All rights reserved.