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 プロパティページ

● 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回に別けます。