Last Updated 2004/03/08
Visual C++ API
ExitWindowsEx
2004/03/08

Windows95 をプログラムから終了させる.

電源を切れる状態にする
ExitWindowsEx( EWX_SHUTDOWN, 0 );

コンピュータを再起動する
ExitWindowsEx( EWX_REBOOT, 0 );

Windowsにログオンし直す
ExitWindowsEx( EWX_LOGOFF, 0 );

Windows再起動
Windows3.1 では ExitWindows( EW_RESTARTWINDOWS, 0 ) で可能であるが,Window95 ではできない.
何らかの手段で 16bit ExitWindows() を呼び出す必要がある.VC++1.5 で ExitWindows を実行するプログラムを作って,それを呼び出すのが楽かもしれない.
(スタートメニューの終了時 Shift ボタンを押しながら再起動させると,16bit の User.exe の ExitWindows() が呼び出されるという噂がある)


スタートメニューの終了時に Shift ボタンを押しながら再起動させると,「Windows9xを再起動しています...」
とメッセージを表示する.これもやはり 16bit の関数を呼び出さなければならない.
しかし,発想を変えて以下の様にする方法もある.
WinExec("rundll.exe user.exe,exitwindowsexec", SW_SHOW);


MS-DOSモードで再起動
WINDOWS\MS-DOSモード.PIF を ShellExecuteEx() で起動すれば生 DOS を起動する.
この時,Win.com は 5344414D.bat も実行する.
( WINDOWS\SYSTEM\5344414D.bat を削除すると MS-DOS へ抜けることができなくなる)


void RunExitWindows(UINT uFlags, DWORD dwReserved)
{
    static HANDLE              hToken;
    static TOKEN_PRIVILEGES    tkp;
    static SECURITY_ATTRIBUTES sa;

    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;

    if( !OpenProcessToken(GetCurrentProcess(),
                          (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY),
                          &hToken) ) {
        return;
    }

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

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges(hToken,
                          FALSE,
                          &tkp,
                          0,
                          (PTOKEN_PRIVILEGES)NULL,
                          0);

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

    // リブートの場合
    if( ((EWX_REBOOT | EWX_FORCE) & uFlags) == (EWX_REBOOT | EWX_FORCE) ) {
        ExitWindowsEx(uFlags, dwReserved);
        return;
    }

    // シャットダウンの場合
    if( ((EWX_SHUTDOWN | EWX_FORCE) & uFlags) == (EWX_SHUTDOWN | EWX_FORCE) ) {
        ExitWindowsEx(uFlags, dwReserved);
        return;
    }

    // ログオフの場合
    if( ((EWX_LOGOFF | EWX_FORCE) & uFlags) == (EWX_LOGOFF | EWX_FORCE) ) {
        PostMessage(FindWindow("ProgMan", NULL), WM_CLOSE, 0, 0);
        return;
    }
}


参照
ExtiWindows
電源遮断
前後のTips
ExitWindowsEx

DSS ProgrammingTipsCGI Ver1.02