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

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

  その1はレジストリの説明をしました。
  その2ではファイルアクセスの例を示します。
  XP/2003までは、Administratorsグループに所属しているアカウントはProgram Filesにファイルを作成・書き込む・削除することができました。
  Windows Vistaでは、Administratorsグループに所属しているアカウントでも「Program Files」のファイルを直接操作することはできませんが、プログラム上では成功しているように見えます。

  以下は、Vistaでは、管理者権限へ権限上昇しなくても書き込みは成功しますが、権限上昇しないと、実はユーザーフォルダのVirtualStoreの中に保存されるという例です。

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

//----------------------------------------------------------------------------------------------------
// Program Filesへのファイル書き込み
//   XP/2003まででも、Administratorsグループに所属していないアカウントは動作しない
//   Vistaでは、管理者権限へ権限上昇しなくても書き込みは成功するが、
//   実はユーザーフォルダのVirtualStoreの中に保存される。
//
//   権限上昇しない場合
//   "C:\\Program Files\\sample.txt"を作成した場合、アクセスは成功するが、
//   実際には、下記に保存される
//   "C:\\Users\\[ユーザ名]\\AppData\\Local\\VirtualStore\\Program Files\\sample.txt"
//----------------------------------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>
#include <string>

#include <shlobj.h>

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>

// CSIDL へのパスを取得
std::basic_string < _TCHAR > GetCSIDLPath ( int nCSIDL )
{
    enum
    {
        MY_MAX_PATH = MAX_PATH + 1
    };
    std::basic_string < _TCHAR > strResult;
    ITEMIDLIST *pItemIDList;
    _TCHAR szPath[ MY_MAX_PATH ];

    if ( SUCCEEDED ( SHGetSpecialFolderLocation ( NULL,
        nCSIDL,
        &pItemIDList ) ) )
    {
        if ( SHGetPathFromIDList ( pItemIDList, szPath ) )
        {
            strResult = szPath;
        }

        CoTaskMemFree ( pItemIDList );
    }

    return strResult;
}

// エントリポイント
int WINAPI _tWinMain ( HINSTANCE,
    HINSTANCE,
    _TCHAR *,
    int )
{
// Program Filesへのパスを取得
    std::basic_string < _TCHAR > strProgramFilesPath;
    strProgramFilesPath = GetCSIDLPath ( CSIDL_PROGRAM_FILES );

// ファイルパス作成
    const _TCHAR cszSample[] = _TEXT ( "\\sample.txt" );
    std::basic_string < _TCHAR > strPath;
    strPath = strProgramFilesPath + cszSample;

// ファイル書き込み作成
    int nHandle;

    // ファイルを開く
    nHandle = _topen ( strPath.c_str (), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IWRITE );
    if ( -1 == nHandle )
    {
        MessageBox ( NULL,
            _TEXT ( "ファイルを開くことができません" ),
            _TEXT ( "エラー" ),
            MB_OK | MB_ICONSTOP );
        return 0;
    }

    const char csz[] = "sample";
    // ファイルを書き込み
    if ( -1 == _write ( nHandle, csz, ( sizeof ( csz ) - 1 ) * sizeof ( char ) ) )
    {
        MessageBox ( NULL,
            _TEXT ( "ファイルを書き込むことができません" ),
            _TEXT ( "エラー" ),
            MB_OK | MB_ICONSTOP );
        // ファイルを閉じる
        _close ( nHandle );
    }

// 管理者権限へ権限上昇していないと、実際にはstrPathには書き込まれませんが
// 処理は成功したことになります。
    MessageBox ( NULL,
        strPath.c_str (),
        _TEXT ( "下記に作成しました" ),
        MB_OK );
    _close ( nHandle );

    return 0;
}


  上記を管理者権限へ権限上昇せずに実行し、実行したWindowsアカウントのフォルダを開いてみましょう。
  アクセスしたパスではなく、C:\Users\[ユーザ名]\AppData\Local\VirtualStore\Program Files\sample.txt に書き込まれたことがわかります。

  管理者権限へ権限上昇しなくてもProgram Filesの中身を読み込むことはできますが、権限上昇せずに書き込もうとすると権限がないため、パスがVirtualStoreにエミュレートされて書き込まれてしまうのです。

  今度は、管理者権限へ権限上昇するようにrequireAdministratorにしてみましょう。

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

write_prgf2のmain.cppと同じソース

■resrc.rc
1 24 "write_prgf2.exe.manifest"
■write_prgf2.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="write_prgf2.exe"
       type="win32"/>

    <description>Privilege's elevation for writeprgf2</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>

  今度はProgram Filesに実際書き込むことができました。

  以上からわかるように、
    Administratorsグループに所属していても、XPまでのように最高権限としては動作しません。
    システムの内容の「読み込み」権限はありますが、「変更」「作成」「書き込み」権限がありません。場合によってはエミュレートされます。
  これはレジストリ・ファイルに限った話ではありません。

  ■ ご利用に際して ■ 更新履歴 ■ お問い合わせ ■ このホームページについて Copyright © 2014 A.Morita