c++ builder > shutdown処理 > XE4, 10.2 Tokyo 対応 > ログオフ


動作確認
C++ Builder XE4
Rad Studio 10.2 Tokyo Update 2 (追記: 2017/12/27)

シャットダウン処理

http://support.embarcadero.com/article/35937
に記載されているshutdown処理だが、XE4ではいくつか変更しないといけない。

以下で動作した。

Unit1.cpp
const wchar_t *ErrOpenProcess     = L"Error OpenProcessToken";
const wchar_t *ErrLookupPrivilege = L"Error LookupPrivilegeValue";
const wchar_t *ErrAdjustToken     = L"Error AdjustTokenPrivileges";
const wchar_t *ErrExitWindowsEx   = L"Error ExitWindowEx";

void __fastcall TForm1::AccessPrivilege( wchar_t *Prvlg, String ServerName, bool Mode ) throw(Exception)
{
    HANDLE htoken;
    TOKEN_PRIVILEGES  tknPrvlgs;

    bool success = OpenProcessToken( GetCurrentProcess(),
                             TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &htoken );
    if( !success ){
        throw Exception(ErrOpenProcess);
    }

    success = LookupPrivilegeValue( ServerName.c_str(), Prvlg, &(tknPrvlgs.Privileges[0].Luid) );

    if( !success ) {
        throw Exception(ErrLookupPrivilege);
    }

    tknPrvlgs.PrivilegeCount = 1;

    if( Mode ) {
        tknPrvlgs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    } else {
        tknPrvlgs.Privileges[0].Attributes = 0;
    }

    AdjustTokenPrivileges( htoken, false, &tknPrvlgs, sizeof(TOKEN_PRIVILEGES), 0, 0 );

    //AdjustTokenPrivileges は常に true を返すのが仕様らしい?
    //SDK の Help のサンプルにも GetLastError で記述されている
    if( GetLastError() != ERROR_SUCCESS )
    {
        throw Exception( ErrAdjustToken );
    }

}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    try{
        AccessPrivilege( SE_SHUTDOWN_NAME, "", true );
    }catch( Exception &Ex ){
        OutputDebugString( Ex.Message.c_str() );
        return;
    }

    if(!ExitWindowsEx( EWX_SHUTDOWN | EWX_FORCE, 0 )) {
        OutputDebugString( ErrExitWindowsEx );
    }

    try{
        AccessPrivilege( SE_SHUTDOWN_NAME, "", false );
    }catch( Exception &Ex ){
        OutputDebugString( Ex.Message.c_str() );
        return;
    }
}

この処理がXE4やXE10などでも最適な方法かはわからない。

別のサイトでdelphi XEシリーズでの実装例があるが、それをC++ builderに変更しようとして失敗したので、上記ページを参考にした。

ログオフ処理

if(!ExitWindowsEx( EWX_SHUTDOWN | EWX_FORCE, 0 )) {
の部分を
if(!ExitWindowsEx( EWX_LOGOFF| EWX_FORCE, 0 )) {
とすればログオフできる。

参考 MSDN