Remote Shut Down


Microsoft Windows provides several functions (called WNet functions) that help us in implementing networking capabilities in our application. In this article we will shut down a remote machine from our machine.

  1. Create a dialog-based application using AppWizard and give the project name as RemoteShutDown.
  2. Add controls to the dialog template as shown in the following figure.

    The controls, their IDs and variables associated with them are given in the following table.

    Control

    ID

    Variable

    Type

    Machine Name edit box

    IDC_NAME

    m_mname CString
    Alert edit box

    IDC_MSG

    m_msg CString

    Machine Password edit box

    IDC_PWD

    m_pwd CString
    Restart check box

    IDC_RST

    m_rst BOOL

    Force application shutdown check box

    IDC_FAS

    m_fas BOOL
    ShutDown button IDC_SD    
    Close button IDOK    

     

  3.  #include "winnetwk.h" file and link 'mpr.lib' library file. To link the file, select ‘Project | Settings | Link’ and in the edit box ‘Object/library modules’ type ‘mpr.lib’.
  4. Create handlers for the ‘ShutDown’ button and add the following code to it.

void CRemoteShutDownDlg::OnSd() 
{
    // TODO: Add your control notification handler code here
    UpdateData ( TRUE ) ;
    If ( m_mname == "" )
    {
        AfxMessageBox ( "Name of computer cannot be blank...." ) ;
    }
    else
    {
        LPSTR lpMachineName = ( LPSTR ) ( LPCTSTR ) m_mname ;
        LPSTR lpMessage = ( LPSTR ) ( LPCTSTR ) m_msg ;
        DWORD dwTimeout = 10 ;
        BOOL bForceAppsClosed = m_fas ;
        BOOL bRebootAfterShutdown = m_rst ;
        
        HANDLE hToken ;
        TOKEN_PRIVILEGES TokenPrivileges ;
        WnetAddConnection ( ( LPCTSTR ) m_mname, ( LPCTSTR ) m_pwd, NULL ) ;
        OpenProcessToken ( GetCurrentProcess ( ), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_ALL_ACCESS, &hToken ) ;
        LookupPrivilegeValue( NULL, SE_REMOTE_SHUTDOWN_NAME, &( TokenPrivileges.Privileges[0].Luid ) ) ;
        TokenPrivileges.PrivilegeCount = 1 ;
        TokenPrivileges.Privileges[0].Attributes = 2 ;
        AdjustTokenPrivileges ( hToken, FALSE, &TokenPrivileges, sizeof ( TOKEN_PRIVILEGES ), NULL, NULL ) ;
    
        if ( !InitiateSystemShutdown ( lpMachineName, //lpMachineName, // name of computer to shut down 
                lpMessage, // address of message to display
                dwTimeout, // time to display dialog box 
                bForceAppsClosed, // force applications with unsaved changes flag 
                bRebootAfterShutdown ) )
                    AfxMessageBox ( "Remote Shutdown Failed...." ) ;
        else
                    AfxMessageBox ( "Operation Successful !!...." ) ;
    }
}

Here, we have collected the values of the controls in the variables by calling UpdateData( TRUE ). Through the function, WNetAddConnection( ), we connect to the specified machine, that is, the machine to be shut down, by specifying the name of the machine and the password for the machine that should be provided by the user.

To shut down a remote computer, the calling process, that is, our application must have the proper privileges on the remote computer.The privileges required by the current process are adjusted by the functions OpenProcessToken( ), LookupPrivilegeValue( ) and AdjustTokenPrivileges( ).

The OpenProcessToken( ) function opens the access token associated with a process. The handle to our application is to be passed to this function. To obtain the handle to our application, the GetCurrentProcess( ) function is used. The desired access is specified as the second parameter and the third parameter is a pointer to a handle identifying the newly-opened access token.

The LookupPrivilegeValue( ) function retrieves the locally unique identifier (LUID) used on a specified system to locally represent the specified privilege name. The first parameter to this function is a pointer to a null-terminated string specifying the name of the system on which the privilege name is looked up. We have specified this parameter as NULL because we wish to find the privilege name on the local system. The second parameter is a pointer to a null-terminated string that specifies the name of the privilege and the third parameter is a pointer to a variable that receives the locally unique identifier by which the privilege is known on the system specified by the first parameter.

The AdjustTokenPrivileges( ) function enables or disables privileges in the specified access token. Enabling or disabling privileges in an access token requires TOKEN_ADJUST_PRIVILEGES access.

The InitiateSystemShutdown( ) function initiates a shutdown and optional restart of the specified computer. After adjusting the privileges of our application, a call to the InitiateSystemShutdown( ) function is made which actually shuts down the remote computer. The first parameter to this function is a pointer to the null-terminated string that specifies the network name of the computer to shut down. If this parameter is NULL or points to an empty string, the function shuts down the local computer. The second parameter is a pointer to a null-terminated string that specifies a message to display in the shutdown dialog box. This parameter can be NULL if no message is required. The third parameter specifies the time (in seconds) that the dialog box should be displayed. While this dialog box is displayed, the shutdown can be stopped by the AbortSystemShutdown( ) function.

If the third parameter is not zero, InitiateSystemShutdown( ) displays a dialog box on the specified computer. The dialog box displays the name of the user who called the function, displays the message specified by the second parameter, and prompts the user to log off. The dialog box beeps when it is created and remains on top of other windows in the system. The dialog box can be moved but not closed. A timer counts down the remaining time before a forced shutdown. If the user logs off, the system shuts down immediately. Otherwise, the computer is shut down when the timer expires. If the third parameter is zero, the computer shuts down without displaying the dialog box, and the shutdown cannot be stopped by AbortSystemShutdown( ).

The fourth parameter specifies whether applications with unsaved changes are to be forcibly closed. If this parameter is TRUE, such applications are closed. If this parameter is FALSE, a dialog box is displayed prompting the user to close the applications. The last parameter specifies whether the computer is to restart immediately after shutting down. If this parameter is TRUE, the computer is to restart. If this parameter is FALSE, the system flushes all caches to disk, clears the screen, and displays a message indicating that it is safe to power down.

Download