Programming Windows Maniacs - プログラミング ウィンドウズ マニアックス ■ ご利用に際して ■ 更新履歴 ■ お問い合わせ ■ このホームページについて  
ホーム >> OS >> Windows®Vista™ >> 管理者権限への権限上昇が必要なのはどのようなときか - その1

管理者権限への権限上昇が必要なのはどのようなときか - その1

  そもそも管理者権限への権限上昇が必要なのはどのようなときでしょうか。
  一番身近なプログラムの実例として、レジストリがあります。
  HKEY_LOCAL_MACHINEのシステム領域などは、各ユーザごとではなくシステムなので、変更や書き込みができません。読み込みはできます。
  HKEY_CURRENT_USERは、書き込み・変更・読み込みが可能です。

  以下は、HKEY_LOCAL_MACHINEでもシステム領域でなければ権限上昇しなくても書き込み可能という例です。Vistaで問題なく動作します。

■■■ HKLM プロジェクト
■ main.cpp

//----------------------------------------------------------------------------------------------------
// HKEY_LOCAL_MACHINEに「レジストリのキーを作成」し、「値を書き込む」 サンプル
//----------------------------------------------------------------------------------------------------

#include <windows.h>
#include <tchar.h>

int WINAPI _tWinMain ( HINSTANCE,
    HINSTANCE,
    _TCHAR *,
    int )
{
    HKEY hRootKey;
    hRootKey = HKEY_LOCAL_MACHINE;

    DWORD dwDisposition;
    HKEY hSubKey;
    LONG lResult;


//----------------------------------------------------------------------------------------------------
// "HKEY_LOCAL_MACHINE\\Software" に関するテスト
//----------------------------------------------------------------------------------------------------

// サブキー作成 "HKEY_LOCAL_MACHINE\\Software\\Sample"
    // ユーザー領域なので、キーを作成できる
    const _TCHAR cszSoftwareSubKey[] = _TEXT ( "Software\\Sample" );
    lResult = RegCreateKeyEx ( hRootKey,
        cszSoftwareSubKey,
        0,
        NULL,
        REG_OPTION_NON_VOLATILE,
        KEY_ALL_ACCESS,
        NULL,
        &hSubKey,
        &dwDisposition );
    if ( ERROR_SUCCESS == lResult )
    {
        MessageBox ( NULL,
            _TEXT ( "RegCreateKeyEx 成功" ),
            cszSoftwareSubKey,
            MB_OK );
    }
    else
    {
        MessageBox ( NULL,
            _TEXT ( "RegCreateKeyEx 失敗" ),
            cszSoftwareSubKey,
            MB_OK | MB_ICONSTOP );
        return 0;
    }

// 値 書き込み
    // ユーザー領域なので、値を作成できる
    const _TCHAR cszSoftwareValueName[] = _TEXT ( "SampleValue" );
    const _TCHAR cszSoftwareValue[] = _TEXT ( "Sample" );
    DWORD dwSize = sizeof ( cszSoftwareValue );
    lResult = RegSetValueEx ( hSubKey,
        cszSoftwareValueName,
        0,
        REG_SZ,
        reinterpret_cast < const BYTE * > ( cszSoftwareValue ),
        dwSize );
    if ( ERROR_SUCCESS == lResult )
    {
        MessageBox ( NULL,
            _TEXT ( "RegSetValueEx 成功" ),
            cszSoftwareSubKey,
            MB_OK );
    }
    else
    {
        MessageBox ( NULL,
            _TEXT ( "RegSetValueEx 失敗" ),
            cszSoftwareSubKey,
            MB_OK | MB_ICONSTOP );
        // 解放
        RegCloseKey ( hSubKey );
        return 0;
    }

    int nResponse;
    nResponse = MessageBox ( NULL,
        _TEXT ( "値を削除しますか?" ),
        cszSoftwareSubKey,
        MB_YESNO | MB_ICONQUESTION );
    if ( IDYES == nResponse )
    {
    // 値 削除
        // ユーザー領域なので、値を作成できる
        lResult = RegDeleteValue ( hSubKey, cszSoftwareValueName );
        if ( ERROR_SUCCESS == lResult )
        {
            MessageBox ( NULL,
                _TEXT ( "RegDeleteValue 成功" ),
                cszSoftwareSubKey,
                MB_OK );
        }
        else
        {
            MessageBox ( NULL,
                _TEXT ( "RegDeleteValue 失敗" ),
                cszSoftwareSubKey,
                MB_OK | MB_ICONSTOP );
            // 解放
            RegCloseKey ( hSubKey );
            return 0;
        }
    }
    else
    {
        // 値 削除しない
    }

// キーを閉じる
    RegCloseKey ( hSubKey );

//----------------------------------------------------------------------------------------------------
// "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\CurrentVersion\\Run" に関するテスト
//----------------------------------------------------------------------------------------------------
// サブキー作成 "HKEY_LOCAL_MACHINE\\Software\\Sample"
    // 基本的にすでにあるので Vistaでも成功する
    // ただし、元々ない場合は、システム領域なので、管理者権限へ権限上昇しないと、キーの作成に失敗する
    //   たとえば、Software\\Microsoft\\Windows\\CurrentVersion\\Run2 の作成は失敗する
    const _TCHAR cszRunSubKey[] = _TEXT ( "Software\\Microsoft\\Windows\\CurrentVersion\\Run" );
    lResult = RegCreateKeyEx ( hRootKey,
        cszRunSubKey,
        0,
        NULL,
        REG_OPTION_NON_VOLATILE,
        KEY_ALL_ACCESS,
        NULL,
        &hSubKey,
        &dwDisposition );
    if ( ERROR_SUCCESS == lResult )
    {
        MessageBox ( NULL,
            _TEXT ( "RegCreateKeyEx 成功" ),
            cszRunSubKey,
            MB_OK );
    }
    else
    {
        MessageBox ( NULL,
            _TEXT ( "RegCreateKeyEx 失敗" ),
            cszRunSubKey,
            MB_OK | MB_ICONSTOP );
        return 0;
    }

// 値 書き込み -- Vistaではここで失敗する。
    // 管理者権限へ権限上昇しないとシステム領域への書き込みはできない。
    const _TCHAR cszRunValueName[] = _TEXT ( "Notepad" );
    const _TCHAR cszRunValue[] = _TEXT ( "C:\\Windows\\notepad.exe" );
    dwSize = sizeof ( cszRunValue );
    lResult = RegSetValueEx ( hSubKey,
        cszRunValueName,
        0,
        REG_SZ,
        reinterpret_cast < const BYTE * > ( cszRunValue ),
        dwSize );
    if ( ERROR_SUCCESS == lResult )
    {
        MessageBox ( NULL,
            _TEXT ( "RegSetValueEx 成功" ),
            cszRunSubKey,
            MB_OK );
    }
    else
    {
        MessageBox ( NULL,
            _TEXT ( "RegSetValueEx 失敗" ),
            cszRunSubKey,
            MB_OK | MB_ICONSTOP );
        // 解放
        RegCloseKey ( hSubKey );
        return 0;
    }

    nResponse = MessageBox ( NULL,
        _TEXT ( "値を削除しますか?" ),
        cszRunSubKey,
        MB_YESNO | MB_ICONQUESTION );
    if ( IDYES == nResponse )
    {
    // 値 削除
        // 管理者権限へ権限上昇しないとシステム領域への書き込みはできない。
        lResult = RegDeleteValue ( hSubKey, cszRunValueName );
        if ( ERROR_SUCCESS == lResult )
        {
            MessageBox ( NULL,
                _TEXT ( "RegDeleteValue 成功" ),
                cszRunSubKey,
                MB_OK );
        }
        else
        {
            MessageBox ( NULL,
                _TEXT ( "RegDeleteValue 失敗" ),
                cszRunSubKey,
                MB_OK | MB_ICONSTOP );
            // 解放
            RegCloseKey ( hSubKey );
            return 0;
        }
    }
    else
    {
        // 値 削除しない
    }

    RegCloseKey ( hSubKey );

    return 0;
}


  上記は、権限上昇しなくても動作しますが、下記のようにシステム領域を操作する際は権限上昇が必要です。

■■■ HKLM2 プロジェクト
■ main.cpp

//----------------------------------------------------------------------------------------------------
// HKEY_LOCAL_MACHINEに「レジストリのキーを作成」し、「値を書き込む」 サンプル
//   管理者権限への権限上昇を必須としているので、実行できる限り必ず成功します!
//----------------------------------------------------------------------------------------------------

#include <windows.h>
#include <tchar.h>

int WINAPI _tWinMain ( HINSTANCE,
    HINSTANCE,
    _TCHAR *,
    int )
{
    HKEY hRootKey;
    hRootKey = HKEY_LOCAL_MACHINE;

    DWORD dwDisposition;
    HKEY hSubKey;
    LONG lResult;

    DWORD dwSize;
    int nResponse;
//----------------------------------------------------------------------------------------------------
// "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\CurrentVersion\\Run" に関するテスト
//----------------------------------------------------------------------------------------------------
// サブキー作成 "HKEY_LOCAL_MACHINE\\Software\\Sample"
    // 基本的にすでにあるので Vistaでも成功する
    // ただし、元々ない場合は、システム領域なので、管理者権限へ権限上昇しないと、キーの作成に失敗する
    //   たとえば、Software\\Microsoft\\Windows\\CurrentVersion\\Run2 の作成は失敗する
    const _TCHAR cszRunSubKey[] = _TEXT ( "Software\\Microsoft\\Windows\\CurrentVersion\\Run" );
    lResult = RegCreateKeyEx ( hRootKey,
        cszRunSubKey,
        0,
        NULL,
        REG_OPTION_NON_VOLATILE,
        KEY_ALL_ACCESS,
        NULL,
        &hSubKey,
        &dwDisposition );
    if ( ERROR_SUCCESS == lResult )
    {
        MessageBox ( NULL,
            _TEXT ( "RegCreateKeyEx 成功" ),
            cszRunSubKey,
            MB_OK );
    }
    else
    {
        MessageBox ( NULL,
            _TEXT ( "RegCreateKeyEx 失敗" ),
            cszRunSubKey,
            MB_OK | MB_ICONSTOP );
        return 0;
    }

// 値 書き込み -- Vistaではここで失敗する。
    // 管理者権限へ権限上昇しないとシステム領域への書き込みはできない。
    const _TCHAR cszRunValueName[] = _TEXT ( "Notepad" );
    const _TCHAR cszRunValue[] = _TEXT ( "C:\\Windows\\notepad.exe" );
    dwSize = sizeof ( cszRunValue );
    lResult = RegSetValueEx ( hSubKey,
        cszRunValueName,
        0,
        REG_SZ,
        reinterpret_cast < const BYTE * > ( cszRunValue ),
        dwSize );
    if ( ERROR_SUCCESS == lResult )
    {
        MessageBox ( NULL,
            _TEXT ( "RegSetValueEx 成功" ),
            cszRunSubKey,
            MB_OK );
    }
    else
    {
        MessageBox ( NULL,
            _TEXT ( "RegSetValueEx 失敗" ),
            cszRunSubKey,
            MB_OK | MB_ICONSTOP );
        // 解放
        RegCloseKey ( hSubKey );
        return 0;
    }

    nResponse = MessageBox ( NULL,
        _TEXT ( "値を削除しますか?" ),
        cszRunSubKey,
        MB_YESNO | MB_ICONQUESTION );
    if ( IDYES == nResponse )
    {
    // 値 削除
        // 管理者権限へ権限上昇しないとシステム領域への書き込みはできない。
        lResult = RegDeleteValue ( hSubKey, cszRunValueName );
        if ( ERROR_SUCCESS == lResult )
        {
            MessageBox ( NULL,
                _TEXT ( "RegDeleteValue 成功" ),
                cszRunSubKey,
                MB_OK );
        }
        else
        {
            MessageBox ( NULL,
                _TEXT ( "RegDeleteValue 失敗" ),
                cszRunSubKey,
                MB_OK | MB_ICONSTOP );
            // 解放
            RegCloseKey ( hSubKey );
            return 0;
        }
    }
    else
    {
        // 値 削除しない
    }

    RegCloseKey ( hSubKey );

    return 0;
}

■resrc.rc
1 24 "HKLM2.exe.manifest"
■mnfst.exe.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity version="1.0.0.0"
       processorArchitecture="X86"
       name="HKLM2.exe"
       type="win32"/>

    <description>Privilege's elevation for HKLM2</description>
    <!-- Identify the application security requirements. -->
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
            <requestedPrivileges>
                <requestedExecutionLevel
                  level="requireAdministrator"
                  uiAccess="false"/>
            </requestedPrivileges>
        </security>
    </trustInfo>

<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="X86"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
</assembly>
  ■ ご利用に際して ■ 更新履歴 ■ お問い合わせ ■ このホームページについて Copyright © 2014 A.Morita