検索 
2010年9月10日 ..:: ブログ ::..   ログイン


 Programming
UAC (User Account Control) と C/C++ MFC アプリケーション(その2)
By : Akira INOUE   Date : 2007/03/19 17:15

前回の記事「UAC (User Account Control)と C/C++ MFC アプリケーション(その1)」の続きです。

前回は、Application ManifestsVirtualization について解説しました。今回は、それらの組み合わせによるアプリケーションの挙動についてサンプルアプリケーションを元に解説します。

マニフェストなし、または requestedExecutionLevel 要素記述なしの場合

この場合は、Virtualization 機能により、権限のないフォルダやレジストリキーへの書き込みがリダイレクトされ、エラー無く実行されます。ただし、この場合に注意が必要なのは、インストール時に設定情報などのファイルを %PorgramFiles% のインストールフォルダにインストールし、そのファイルをアプリケーション実行時に読み書き可能なモードで開いたりした場合に、%USERPROFILE%\AppData\Local\VirtualStore\Program Files\ 以下のフォルダにリダイレクトされるので、設定情報が読み込めないなどの不具合が発生する可能性があります。

図:サンプルアプリケーションの実行(マニフェスト無しの場合)
AppNoManifest.JPG

C:\Program Files\BitWiz\test.txt の作成に成功している(上図)が、C:\Program Files\BitWiz には test.txt が生成されていない(下図)。

図:サンプルアプリケーションの実行フォルダ
NoManifestFolder.JPG

Virtualization(仮想化)機能により、C:\Users\\AppData\Local\VirtualStore\Program Files\BitWiz フォルダに test.txt が生成されている(下図)。

図:C:\Users\\AppData\Local\VirtualStore\Program Files\BitWiz フォルダ
NoManifestVirtualStore.JPG

サンプルアプリケーションの実行結果では、HKEY_LOCAL_MACHINE\SOFTWARE\BitWiz のレジストリキーのオープン(KEY_ALL_ACCESS)に成功しているが、実際は HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\SOFTWARE\BitWiz キーがオープンされて値が取得されている。

図:レジストリキーのリダイレクト
NoManifestRegVirtualStore.JPG


マニフェストありで、requestedExecutionLevel 要素記述ありの場合

Virtualization 機能は無効となり、仮想化(ファイルやレジストリのリダイレクション)は行われません。

asInvoker
requestedExecutionLevel 要素の level 属性値を asInvoker とした場合、親プロセスと同じ特権で実行されるため、書き込み権限のない C:\Program FilesHKEY_LOCAL_MACHINE への書き込みなどはエラーとなります。

図:サンプルアプリケーションの実行(マニフェストあり(asInvoker)の場合)
AppAsInvoker.JPG

asInvoker 属性値により権限の昇格なしで実行されているため、ファイルの作成、レジストリキーのアクセスともに失敗している。Virtualization 機能も無効となり、リダイレクトも行われない。

highestAvailable / requireAdministrator
requestedExecutionLevel 要素の level 属性値に highestAvailablerequireAdministrator とすると、実行時に UAC 昇格確認ダイアログが表示される。
ここで、実行を許可すると C:\Program FilesHKEY_LOCAL_MACHINE への書き込みなどが可能となる。

図:実行時の UAC ダイアログ
UACDialog.jpg

実行時に必ず UAC 昇格確認ダイアログが表示される(上図)。

図:サンプルアプリケーションの実行(マニフェストあり(requireAdministrator)の場合)
AppRequireAdministrator.JPG

ファイルの作成、レジストリキーのアクセス共に成功している(上図)。

図:サンプルアプリケーションの実行フォルダ
AdminFolder.JPG

C:\Program Files\BitWiz\test.txt が生成されている。
また、マニフェストの requireAdministrator 属性値により、自動でアプリケーションアイコンにシールドアイコンが表示され、権限の昇格を行わないと実行できないことがわかる(上図)。

図:HKEY_LOCAL_MACHINE レジストリキーへのアクセス
AdminReg.JPG

指定どおり、HKEY_LOCAL_MACHINE\SOFTWARE\BitWiz レジストリキーのオープン(KEY_ALL_ACCESS)に成功している(上図)。


インストーラ検出技術の条件に一致した場合

基本的には requestedExecutionLevel 要素の level 属性値が優先されますが、この要素記述が無い場合は "install" "setup" "update" などのキーワードがファイル名やバージョンリソースに含まれるとインストーラと判断され、UAC 昇格確認ダイアログが表示されることとなります。

図:ファイル名に "Setup" という文字列を含んだアプリケーション
SetupApp.JPG

マニフェストに requestedExecutionLevel 要素の記述を行っていないが、アプリケーションアイコンにシールドアイコンが表示されている(上図)。

図:インストーラとして検出されたアプリケーションの終了後に表示される確認ダイアログ
SetupAppAfter.JPG

アプリケーション実行終了後、正しくインストールされたかの確認ダイアログが表示される(上図)。

さて、アプリケーションがインストーラとして検出される条件はどのようになっているのでしょうか?

以下は
「Installer Detection Technology」
http://technet.microsoft.com/en-us/windowsvista/aa905117.aspx
からの抜粋です。

Installer Detection only applies to:

1. 32 bit executables
2. Applications without a requestedExecutionLevel
3. Interactive processes running as a Standard User with LUA enabled

Before a 32 bit process is created, the following attributes are checked to determine whether it is an installer:

- Filename includes keywords like "install," "setup," "update," etc.
- Keywords in the following Versioning Resource fields: Vendor, Company Name, Product Name, File Description, Original Filename, Internal Name, and Export Name.
- Keywords in the side-by-side manifest embedded in the executable.
- Keywords in specific StringTable entries linked in the executable.
- Key attributes in the RC data linked in the executable.
- Targeted sequences of bytes within the executable.

ファイル名だけでなはく、バージョンリソースなどに含まれるキーワードでも判断されるようです。

UAC 対応のシナリオ

■ 意図的に仮想化(Virtualization)させる場合

アプリケーションマニフェストに requestedExecutionLevel 要素の記述を行わない。
※注意点
インストール時等に C:\Program Files にコピーされたファイルなどへの読み書きを前提にしている場合、そのファイルをWriteで開く時点で C:\Users\\AppData\Local\VirtualStore\Program Files\ にリダイレクトされるので、ファイルが存在しないなどのエラーとなる。

■ 仮想化(Virtualization)を行わずに、且つファイルやレジストリへのアクセス権限も正しく行っていて、管理者権限での実行が不要な場合。もしくは実行ファイル名に "install", "setup", "update" などの文字を含める必要があるが、インストーラとして認識されたくない場合

アプリケーションマニフェストに requestedExecutionLevel 要素の記述を行い level 属性値を asInvoker とする。

■ 仮想化(Virtualization)は行いたくないが、Program Files や HKEY_LOCAL_MACHINE などへの書き込み参照が必要な場合

アプリケーションマニフェストに requestedExecutionLevel 要素の記述を行い level 属性値を requireAdministrator とする。

■ 仮想化(Virtualization)を行い、かつファイル名などに "install", "setup", "update" などの文字を含める必要がある場合

不可能。必ずインストーラとして認識されてしまい管理者権限に昇格しないと実行できないため、この場合は仮想化を行うことはできない。

おわりに

Windows Vista 対応のアプリケーションを開発する場合、UAC への理解が必須と思われますが、慣れないうちはなかなかわかりにくいところです。
今回は、マニフェストをアプリケーションリソースに埋め込む方法でいろいろと試してみましたが、マニフェストを外部ファイルとして実行ファイルと同じフォルダに置いた場合、若干異なる動きをすることを確認しています。時間がとれればそのあたりも調べてみたいと思っていますが、とりあえずは、埋め込みマニフェストを使い、アプリケーションの権限昇格の要/不要を制御するか、Virtualization 機能を前提としたアプリケーション実装を行うことが確実でしょう。
また、Authenticode 証明書などでアプリケーションに署名を行うと、UAC の昇格確認ダイアログの表示が変わったりするのですが、今回は署名されている場合の説明は割愛します。

詳細...

UAC (User Account Control) と C/C++ MFC アプリケーション(その1)
By : Akira INOUE   Date : 2007/03/19 16:45

Windows Vista の UAC (User Account Control) と、C/C++ MFC アプリケーションなどのアンマネージ(ネイティブ)アプリケーションについてまとめてみます。

既存の C/C++ & MFC アプリケーションを Windows Vista に対応させるのに、最も注意しなくてはならないのが、UAC (User Account Control) への対応でしょう。

アプリケーションマニフェストの有無やマニフェストの記述内容によって、UAC 管理下でのアプリケーションの動作がそれぞれ異なります。

Application Manifests

アプリケーションマニフェストとは、アプリケーションが実行時にバインドする共有 side-by-side アセンブリ(WinSxS フォルダにインストールされる mfc80.dll, comctl32.dll 等のネイティブライブラリ)のバージョンを指定したりするための XML ファイルです。

代表的なところでは、Windows XP でビジュアルスタイルを有効にするために comctl32.dll のバージョンを指定するのに多く使用されています。

このアプリケーションマニフェストは、実行ファイルの名前+.exe.manifest (AppName.exe.manifest) として外部 XML ファイルとすることも、アプリケーションにリソースとして埋め込むこともできます。

Visual Studio 2005 で MFC アプリケーションのプロジェクトを作成すると、stdafx.h に以下の記述が生成されて、comctl32.dll のバージョン6を使用するためのアプリケーションマニフェストがデフォルトでアプリケーションリソースとして埋め込まれるようになります。

#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
    ........
#elif defined _M_X64
    ........
#else
    ........
#endif
#endif

外部 XML ファイルとしてマニフェストを用意する方法は簡単ですが、上記のようにアプリケーションリソースとしてマニフェストが埋め込まれている場合、外部マニフェストファイルを使用すると、リソースに埋め込まれたマニフェストが無効になってしまいますので注意が必要です。

MFC アプリケーションを Windows Vista の UAC へ対応させるにあたり、アプリケーションマニフェストが重要な要素となりますが、上記のようなことから、マニフェストはアプリケーションリソースに埋め込む方法を推奨します。ここでも埋め込みマニフェストを使って UAC 対応について解説していきます。

まず、UAC 対応に必要なアプリケーションマニフェストの記述例を下記に示します。

<?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="AppName"
     type="win32"/>

  <description>Description of your application</description>

  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>

        </requestedPrivileges>
       </security>
  </trustInfo>

</assembly>

ここで重要なのが requestedExecutionLevel 要素の level 属性値です。

requestedExecutionLevel のスキーマは下記のとおりです。

<requestedExecutionLevel
   level="asInvoker|highestAvailable|requireAdministrator"
   uiAccess="true|false"/>

level 属性の値には以下のいずれかを記述します。

asInvoker
- アプリケーションは親プロセスと同じトークン(権限)で実行します

highestAvailable
- アプリケーションは現在のユーザが取得できる最も高い特権で実行します

requireAdministrator
- アプリケーションは管理者として実行され、管理者の完全なトークンで実行されることを要求します

通常、管理者権限への昇格が不要なアプリケーションの場合は asInvoker を使い、管理者権限で実行すべきアプリケーションの場合は requireAdministrator を使うことになるでしょう。

Visual Studio 2005 C++ プロジェクトでマニフェストファイルをリソースに埋め込むには、プロジェクトのプロパティの【構成プロパティ】-【マニフェスト ツール】-【入力と出力】で、「追加のマニフェスト ファイル」に上記のマニフェストを記述したファイルを指定するのが簡単です。ここで「埋め込みマニフェスト」が「はい」となっていることも確認してください。

図:VS 2005 プロパティページ
VS_Prop.JPG


● Virtualization

では次に、UAC 対応にあたり Windows Vista のもう一つ重要な機能を解説します。
Windows Vista では、Virtualization(仮想化)という技術により、権限のないフォルダやレジストリキーに書き込みを行った場合に単にエラーとしてしまうのではなく、各ユーザ毎に用意された書き込み可能な特別なフォルダやレジストリキーにリダイレクトして、あたかも何事もなかったかのようにアプリケーションを実行させることができます。

■ ファイルの仮想化(File Virtualization)

%PorgramFiles% などのフォルダへ、書き込み権限を持たないアプリケーションがファイルを生成しようとした場合などに、自動的に %USERPROFILE%\AppData\Local\VirtualStore\Program Files\ へリダイレクトされ、エラーとならずに実行することができます。

【例】
C:\Program Files\Hoge
へファイルを生成しようとすると、実際には

C:\Users\\AppData\Local\VirtualStore\Program Files\Hoge
へファイルが生成される。

■ レジストリの仮想化(Registry Virtualization)

HKEY_LOCAL_MACHINE などのレジストリキーに、書き込み権限を持たないアプリケーションがキーや値を生成使用とした場合、自動的に HKEY_CURRENT_USER\Software\Classes\VirtualStore へリダイレクトされ、エラーとならずに実行することができます。

【例】
HKEY_LOCAL_MACHINE\Software\Hoge
へキーを生成しようとすると、実際には

HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\SOFTWARE\Hoge
へキーが生成される。

◇◇◇

さて、UAC 管理下におけるアプリケーションの挙動は、アプリケーションマニフェストの requestedExecutionLevel 要素の有無や level 属性値の記述により、いろいろと変わってきます。次回は、それらの組み合わせによるアプリケーションの挙動について解説します。

※ブログ記事としては、ちょっと長くなってしまったので、2回に別けます。

 



MCAD


techbank.jp


Copyright © 2005-2008 by BitWiz   使用条件  プライバシー