この件について調べてみた
リダイレクトの挙動の概要は下記である。
--------------- Yes ---------------- Yes
Start ->---| 64bitカーネルの |-----| 32bitバイナリか? |-----> rule A 適用
| Windowsか ? | | |
---------------- ----------------
| No 32bit | No 64bitバイナリである
| カーネルである |
|------------------------------------> rule B 適用
[rule A]
64bit カーネルのWindowsにおいて32bitバイナリは、32bitプロセスとしてWOW 64(Windows On Windows 64)に32bit systemをエミュレートしてもらってその上を走るのでこのルールが適用されます。
HKEY_LOCAL_MACHINE\Software 配下等特定のレジストリキーへのアクセスは、Wow6432Nodeに含まれるロケーションにリダイレクトされます。
HKEY_LOCAL_MACHINE\Software -> (リダイレクト先) HKEY_LOCAL_MACHINE\Software\Wow6432Node
[rule B]
UACによるリダイレクト が行われる
HKEY_LOCAL_MACHINE\SOFTWARE ->(リダイレクト先) HKEY_CURRENT_USER\Software\Classes\VirtualStore
[WOW64環境で走っているかどうかの確認]
WOW64.pas
unit WOW64;
// wether OS is windows
{$IFDEF MSWINDOWS}
// wether target platform is Windows 32bit
{$IFDEF WIN32}
{$DEFINE MYTARGET}
{$ENDIF}
{$ENDIF}
interface
{$IFDEF MYTARGET}
uses Windows;
{$ENDIF}
function IsWOW64 : Boolean;
{$IFDEF MYTARGET}
var
IsWow64Process : function(hProcess : THandle; var Wow64Process : BOOL) : BOOL stdcall;
{$ENDIF}
implementation
function IsWOW64 : Boolean;
{$IFDEF MYTARGET}
var
Flg : BOOL;
begin
Result := False;
@IsWow64Process := GetProcAddress(GetModuleHandle('kernel32.dll'), 'IsWow64Process');
if @IsWow64Process <> nil then begin
if IsWow64Process(GetCurrentProcess, Flg) then Result := Flg;
end;
{$ELSE}
begin
Result := False;
{$ENDIF}
end;
end.
WOW64test.pas // エラーハンドリング をしていません。レジストリ書き込みを伴います。
unit wow64test;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, WOW64,Registry;
type
TForm4 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
procedure TForm4.Button1Click(Sender: TObject);
const
appKey = 'Software\RegTest';
var
RegIni : TRegIniFile;
val : string;
begin
if IsWOW64 then begin
showMessage('This process is running on Wow64');
end else begin
showMessage('This process is not running on Wow64');
end;
RegIni := TRegIniFile.Create(appKey);
RegIni.RootKey := HKEY_CURRENT_USER;
RegIni.WriteInteger('settings', 'value', 3);
end;
end.
XP (32bit) での実行結果
7 Pro (64bit) での実行結果
しかし、レジストリは、 HKEY_CURRENT_USER\RegTest\settings に書き込まれる。なぜ?
なお、UAC制限によるリダイレクトは、Interactive process の場合は行われないらしいが、
Interactive process とは何なのか? 想像するにコマンドラインプログラムは、Interactive processではなさそうだが真相は不明
0 件のコメント:
コメントを投稿