Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

Delphiによる既存アプリケーションのVista対応

Delphi的Vistaサポートのアプローチ

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2007/12/17 11:30

目次

UACへの対処

 Windows Vistaでは、UAC(ユーザーアカウント制御)が強化され、アプリケーションは通常、管理者権限なしで動作します。これにより、マルウェア、トロイ、ウィルス、rootキットなど脆弱性が入り込む余地を軽減します。

ユーザーアカウント制御
ユーザーアカウント制御

 標準ユーザーでは、以下のような操作ができません。

  • 「Program Files」フォルダ内のファイルに対する変更
  • 「Windows」または「Sytem32」フォルダ内のファイルに対する変更
  • 「HKLM\Software」以下にあるレジストリの変更
  • ローカルコンピュータの日時の変更
  • 「サービスアプリケーション」のインストールとアンインストール

 といったものが挙げられます。これらは、従来も推奨されてきたことですが、Vistaからは強制的に操作できないようになっています。

 Program Filesフォルダ下に設定ファイルなどを保存していたケースなどもあると思いますが、このような操作は、自動的にユーザー下のディレクトリにリダイレクトされるようになります。

 UACに関連してWindows Vista向けにアプリケーションを変更するには、以下のいずれかの方針を採ります。

  1. UACの下でも動作するようアプリケーションを修正する
  2. アプリケーションを標準ユーザー権限で動作可能なように修正します。管理タスクは、分離して別の実行可能EXEまたはCOMオブジェクトなどを使います。また、アプリケーションマニフェストでUAC権限レベルを指定するようにします。
  1. 実行時に対処する
  2. アプリケーションそのものには、手を加えず実行時設定で対応します。この方法は、アプリケーションそのものをVistaに適合させるのではない、いわゆる対処療法です。まず、プログラムの「互換性」タブを利用し、アプリケーションが権限を昇格できるようにします。また、必要に応じて、ファイルやフォルダに対するアクセス制御リスト(ACL)を外します。

 1の方法を採った場合、ユーザー固有のデータは、ユーザーのフォルダ/ファイル/レジストリキーに格納するようにします。具体的には、以下のいずれかに書き込みます。

  • 「C:\ProgramData」か「%UserProfile%」
  • レジストリ「HKCU」

 ファイルの格納場所は、 SHGetFolderPath関数を使用して正しい場所を取得するようにします。以下にそれぞれの値で取得できる情報を示します。

取得できる場所
CSIDL_PERSONAL My Documents
CSIDL_APPDATA Application Data, new for NT4
CSIDL_LOCAL_APPDATA non roaming, user\Local Settings\Application Data
CSIDL_COMMON_APPDATA All Users\Application Data
CSIDL_MYPICTURES My Pictures, new for Win2K
CSIDL_COMMON_DOCUMENTS All Users\Documents

 次のコードは、これらの値を取得する例です。

uses
  SHFolder;

function GetFolder(csidl: Integer; 
                   ForceFolder: Boolean = False) : string;
var
  i: Integer;
begin
  SetLength(Result, MAX_PATH);
  if ForceFolder then
    SHGetFolderPath(0, csidl or CSIDL_FLAG_CREATE, 0, 0, PChar(Result))
  else
    SHGetFolderPath(0, csidl, 0, 0, PChar(Result));
  i:= pos(#0, Result);
  if i > 0 then
    SetLength(Result, Pred(i));
end;

function GetLocalAppDataFolder(ForceFolder: Boolean = False) : string;
begin
  Result:= GetFolder(CSIDL_LOCAL_APPDATA, ForceFolder);
end;

 また、必要があるまで不用意にファイルやレジストリを書き込みモードでオープンしないことも重要です。

 管理者権限が必要な操作を行いたいときには、例えば、分離した別の実行可能EXEを以下のようにして呼び出します。

procedure RunAsAdmin(hWnd: WHND; aFile: string; aParameters: string);
var
  sei: TShellExecuteInfoA;
begin
  FileChar(sei, SizeOf(sei), 0);
  sei.cbSize := SizeOf(sei);
  sei.Wnd := hWnd;
  sei.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_FLAG_NO_UI;
  sei.lpVerb := 'runas';
  sei.lpFile := PChar(aFile);
  sei.lpParameters := PChar(aParameters);
  sei.nShow := SW_SHOWNORMAL;
  if not ShellExecuteEx(@sei) then
    RaiseLastOSError;
end;

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • EDN編集部(イーディーエヌ編集部)

    エンバカデロ・デベロッパーネットワーク(EDN)は、ソフトウェア開発者とデータベース技術者のための技術情報サイトです。Delphi、C++Builderをはじめとする開発ツールやER/Studioなどのデータベースツールに関連する技術記事、ビデオなどを提供しています。EDN編集部は、EDN記事と連携...

バックナンバー

連載:CDN CodeZine出張所
All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5