Windows Azure 入門
Windows Azure How-To 集
WCF / WF 入門
ご注意 : 下記記述のうち、レジストリ リフレクションの機能は、Windows 7 / Windows Server 2008 R2 (およびそれ以降の Windows) では削除されることが決まりました。http://www.microsoft.com/japan/whdc/system/platform/64bit/RegReflect.mspx
環境 :Windows Server 2008 R2 Beta
こんにちは。
昨日のイベント講演の際、会場にてご質問を頂いたので記載します。32 bit アプリケーションを 64 bit 環境 (WOW64) へ移す際の注意点についてです。
まず、昨日もお話しましたが、基礎知識として以下を踏まえておいてください。(ご存じの方は読み飛ばしてください)
しかし、上記で、「一般に」、「基本的に」と書いている部分については、下記のような例外もいくつか存在するという点もご注意ください。(これも、昨日の講演でお話した内容と同じです)
さらに、その他の例外として、 システムフォルダやレジストリなどへアクセスしているアプリケーションとかはどうなってしまうのか ? という疑問などもあろうかと思います。例えば、WOW64 のシステムフォルダは %windir%\syswow64 ですから、%windir%\system32 とハードコードされたプログラムは誤った動作をしてしまうのではないか?と心配されることでしょう。ここでは、そうしたシステムフォルダ/ファイルやレジストリなどへのアクセスに関する動作について抑えておくべきポイントを記載します。
ファイルシステムリダイレクト
WOW64 上で動くプロセスでは、system32 フォルダは、ファイルシステムリダイレクター (File System Redirector) と呼ばれる仕組みによって syswow64 にリダイレクトされます。実際に例を見てみましょう。
例えば、下記のネイティブコードを 32bit アプリケーションとしてビルドします。
int _tmain(int argc, _TCHAR* argv[]){ wchar_t pathname[255]; FILE *fp;
_tsetlocale(LC_ALL, _T("")); // 日本語使用
// システムディレクトリの取得実験 GetSystemDirectory(pathname, 255); wprintf_s(L"システムディレクトリ: %s\n", pathname);
// ファイルの書き込み実験 wcscat_s(pathname, L"\\test.log"); if(_wfopen_s(&fp, pathname, L"a")) return 1; fputs("test", fp); fclose(fp); wprintf_s(L"書き込み終了\n");
return 0;}
これを WOW 64 の入った 64 bit 環境で実行すると、Win 32 の GetSystemDirectory 関数は syswow64 ではなく system32 のディレクトリを返します。しかし、実際にシステムディレクトリへの入出力をおこなうと、system32 にリダイレクトされます。
よって、このプログラムの出力結果は以下になり、test.log は %windir%\syswow64 に出力されます。
c:\Demo>Win32TestApp.exeシステムディレクトリ : C:\Windows\system32書き込み終了
マネージコードについても同様です。以下のようなコードを作成し、構成マネージャで x86 で構成してビルドし、このアセンブリを 64 bit (x64) 環境上で実行すると、64 bit 上の .NET Framework ではなく、WOW64 が使用されて 32 bit 版の .NET Framework が動作するため、結果は上記とまったく同じように system32 と出力されますが、実際には syswow64 フォルダにファイル (test.log) が作成されます。
static void Main(string[] args){ // システムディレクトリの取得実験 string pathname = Environment.GetFolderPath(System.Environment.SpecialFolder.System); Console.WriteLine(String.Format("システムディレクトリ : {0}", pathname));
// ファイルの書き込み実験 pathname = Path.Combine(pathname, "test.log"); using (FileStream st = File.Create(pathname)) { // 何もしない . . . st.Close(); }}
ただし、例外のサブフォルダもあるので注意してください。(下記に記載されています)
MSDN ファイルシステムリダイレクター :http://msdn.microsoft.com/en-us/library/aa384187(VS.85).aspx
また、Program Files のフォルダの場合は少々勝手が違ってきます。上記のマネージコードのサンプルで、System.Environment.SpecialFolder.ProgramFiles のようにフォルダ情報を取得すると、返ってくるのは、%systemdrive%\Program Files (x86) フォルダになります。また、%systemdrive%\Program Files フォルダに対してファイルの作成などをおこなってもリダイレクトはされず、そのままそのフォルダに IO がおこなわれます。
レジストリのリダイレクトとリフレクト
同様に、レジストリについても、特定のレジストリキーを作成/オープンする場合に、別のレジストリーキーにリダイレクト (registry redirector) がおこなわれます。
今度は、プログラムではなく、レジストリエディターを使用して動作をみてみましょう。
64 bit 用のレジストリエディタは、パスの通っている %windir%\regedit.exe です。一方、32 bit (WOW 64) 用のレジストリーエディタは %windir%\syswow64\regedit.exe になります。一般にレジストリエディタは複数インスタンスを起動することはできませんので、これら複数のバージョンのエディタを起動するには、複数起動のオプションである %windir%\syswow64\regedit.exe -m といった感じで起動してみてください。(32 bit 用と 64 bit 用の両方が起動します。)
例えば、以下を実施してみてください。(あとで理由はわかりますが、くれぐれも他のサブキーにアクセスせず、下記に忠実に従って実施してみてください。)
これを 64 bit 用のレジストリエディタで覗くと、HKEY_LOCAL_MACHINE\Software\Wow6432Node の下に、まったく同じ構成でキーや値が作成されているのがわかります。実は、WOW 64 上での上記のレジストリアクセスは、すべて HKEY_LOCAL_MACHINE\Software\Wow6432Node の下にリダイレクトされて実行されています。
リダイレクトの対象となるのは以下のキーです。(よって、ここでは詳述しませんが、HKEY_CLASSES_ROOT なども HKEY_LOCAL_MACHINE\Software のサブキーである HKEY_LOCAL_MACHINE\Software\Classes であるため、同様にリダイレクトの対象となります。)
HKEY_LOCAL_MACHINE\SoftwareHKEY_USERS\*\Software\ClassesHKEY_USERS\*_Classes(上記で * は、「S-1-5-18」 などの各 ID を表してします)
レジストリについては、もう 1 つ、別の概念も存在します。今度は 32 bit 用のレジストリエディターで、HKEY_LOCAL_MACHINE\Software\Classes の下に、何か値やキーを作成してみてください。64 bit 側に行くと、さきほどと違い HKEY_LOCAL_MACHINE\Software\Wow6432Node\Classes の下には何も作成されず、HKEY_LOCAL_MACHINE\Software\Classes の下に作成されているのがわかります。
これは、COM の呼び出しなどに備えて実施されているリフレクト (registry reflector) と呼ばれる仕組みで、いわば、32 bit 環境と 64 bit 環境でレジストリーキー/値の同期を取っています。
リフレクトの対象になるのは以下のキーです。
HKEY_LOCAL_MACHINE\Software\ClassesHKEY_LOCAL_MACHINE\Software\Microsoft\COM3HKEY_LOCAL_MACHINE\Software\Microsoft\EventSystemHKEY_LOCAL_MACHINE\Software\Microsoft\OleHKEY_LOCAL_MACHINE\Software\Microsoft\RpcHKEY_USERS\*\Software\ClassesHKEY_USERS\*_Classes
レジストリのこうした動作については、MSDN の下記のドキュメントに詳述されています。
MSDN レジストリ リダイレクターとリフレクター :http://msdn.microsoft.com/en-us/library/aa384232(VS.85).aspxhttp://msdn.microsoft.com/en-us/library/aa384235(VS.85).aspx
なお、このリダイレクトは、読み込み時も同様にリダイレクト (system32 のファイルを読みにいっても、実際には syswow64 から読み込み) されます。
PingBack from http://tune-up-pc.com/blog/?p=1160