Click here to Skip to main content
15,881,380 members
Articles / Programming Languages / C++
Article

Abort system shutdown

Rate me:
Please Sign up or sign in to vote.
2.94/5 (6 votes)
5 Jun 20051 min read 80.5K   1.4K   18   10
Stop the initiated system shutdown without downloading the platform SDK.

Introduction

The AbortSystemShutdown function stops a system shutdown started by using the InitiateSystemShutdown function. The InitiateSystemShutdown function initiates a shutdown and optional restart of the specified computer (see picture below).

System shutdown dialog

There is also another way how to receive this dialog (see picture below): if your computer is infected by the Blaster worm or its variants known as W32.Blaster.Worm, W32.Blaster.C.Worm, W32.Blaster.B.Worm, W32.Randex.E (Symantec), W32/Lovsan.worm (McAfee), WORM_MSBLAST.A (Trendmicro), and Win32.Posa.Worm (Computer Associates).

System shutdown dialog

Code explanation

The AbortSystemShutdown function requires version Windows NT 3.1 or later. Therefore it's useful to use Windows version requirements macros. You can find more information in this article.

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

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

To stop the local computer from shutting down, the calling process must have the SE_SHUTDOWN_NAME privilege. That's the reason why we use the AdjustTokenPrivileges function.

This example also illustrates load-time dynamic linking. If the DLL is not available, the application using load-time dynamic linking must simply terminate. The run-time dynamic linking example, however, can respond to the error.

The code is prepared for UNICODE. If you want to create UNICODE version, add UNICODE to the preprocessor definitions.

The FormatMessage function can be used to obtain error message strings for the system error codes returned by 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);
}

You can get the same result when executing Windows XP shutdown.exe utility with parameter -a. Also you can use shutdown -s -t 60 -c "bye-bye" command to invoke the system Shutdown dialog.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Slovakia Slovakia
Wink | ;-)

Comments and Discussions

 
GeneralSimpliest way Pin
Giou17-Jun-06 22:49
Giou17-Jun-06 22:49 
AnswerRe: Simpliest way Pin
Amir Mohammad Nasrollahi9-Aug-13 22:11
professionalAmir Mohammad Nasrollahi9-Aug-13 22:11 
Generalfailed Pin
aldo hexosa12-Dec-05 2:24
professionalaldo hexosa12-Dec-05 2:24 
GeneralRe: failed Pin
Dalibor Drzik12-Dec-05 6:15
Dalibor Drzik12-Dec-05 6:15 
GeneralRe: failed Pin
Synetech11-Jan-06 19:23
Synetech11-Jan-06 19:23 
GeneralRe: failed Pin
VEMS3-Oct-07 10:22
VEMS3-Oct-07 10:22 
GeneralRe: failed Pin
Synetech3-Oct-07 12:30
Synetech3-Oct-07 12:30 
GeneralRe: failed Pin
VEMS4-Oct-07 2:11
VEMS4-Oct-07 2:11 
GeneralRe: failed Pin
Synetech4-Oct-07 3:55
Synetech4-Oct-07 3:55 
GeneralRe: failed Pin
crashedPilot14-Nov-07 23:49
crashedPilot14-Nov-07 23:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.