WOW64で和訳の練習
あたりを読んでめぼしい情報をメモ。さすがに全部和訳するのはだるい。
(追記)日本語のドキュメントが公開されました! 64 ビット Windows プログラミング ガイド
WOW64の概要
WOW64は以下のユーザーモードDLL群から成る。
- wow64.dll
- コアエミュレーションインフラと、ntoskrnl.exeのエントリーポイント関数のためのサンクを提供する。
- wow64win.dll
- win32k.sysのエントリーポイント関数のためのサンクを提供する。
- wow64cpu.dll
- Itaniumプロセッサにおけるx86命令のエミュレーションを提供する。これはプロセッサのモード遷移命令を実行する。このDLLはx64プロセッサにおいては必要とされない。なぜなら、x86-32命令はネイティブに実行できるためである。
- ia32exec.bin
- (Intel Itaniumのみ)x86ソフトウェアエミュレーター。
- wowia32x.dll
- (Intel Itaniumのみ)ia32exec.binとWOW64の間のインターフェースを提供する。
これらのDLLは64ビットのntdll.dllと協調して動作する。
- 32ビットアプリケーションが動作するとき、まずネイティブライブラリローダーが動作する。
- そのイメージファイルが正しい32ビット形式なら、ローダーは特別にWOW64環境を構築する。
- wow64.dllは32ビット版のntdll.dllをロードし、初期化コードを実行する。
- 次に必要な32ビットDLLをロードする。
- これらのDLLは32ビットWindowsから変更されていないコピーであるが、一部はWOW64においては違うふるまいを見せる。
システムコールの変換
WOW64は32ビットntdll.dllから64ビットntdll.dllへの変換を行ってシステムコールを呼び出し、同様に64ビットntdll.dllから32ビットntdll.dllへの変換を行って値を返却する。
x86システムコールの流れは置き換えられており、特別なシステムコールシーケンスを経るようにリビルドされている。この特別なシステムコールシーケンスでは、WOW64 CPUからネイティブ64ビットモードへ遷移し、wow64.dllを呼び出す。32ビットスタックから引数を取り出し、64ビットに拡張し、ネイティブシステムコールを発行する。このサンクは完全にユーザーモードで行われるため、WOW64によるコストは少なく、サンクの実装におけるデータ破壊や、セキュリティ上のバグがあったとした場合でも、64ビットカーネルへの影響は抑えられる。
注意事項
- ユーザーモードアドレス空間はデフォルトで2GBに制限される。もし/LARGEADDRESSAWAREが指定されていたら4GBに制限される。
- ネイティブ32ビットWindowsの場合、デフォルトで2GB、/LARGEADDRESSAWARE + 4GT RAM Tuningで3GB。
- 64ビットプロセスは32ビットDLLをロードできない。逆もまた然り(ただし一部の64ビットシステムDLLを除く)。
- 16ビットプロセスはサポートされない。
- 仮想DOSマシン(VDM)は無効である。
- 一部のプロセス間の処理を行うAPIは動作しない(32ビットアプリケーションから、64ビットアプリケーションへのCreateRemoteThreadなど)。
- WH_MOUSE, WH_KEYBOARD, WH_JOURNAL*, WH_SHELL, およびローレベルフックはブックチェインの中に32ビットと64ビット両方があるとき、64ビットに先んじて32ビットのフックが呼ばれる。
- (Intel Itaniumのみ)AWE、スキャッター/ギャザーI/O、ライトトラッキングなど、ページサイズに依存するAPIは利用できない。
- (Intel Itaniumのみ)PAEは無効である。
- (Intel Itaniumのみ)DirectXはサポートされない。
プロセスの環境変数
名前 | 64ビット | 32ビット | |
---|---|---|---|
PROCESSOR_ARCHITECTURE | AMD64 or IA64 | x86 | |
PROCESSOR_ARCHITEW6432 | (この変数は存在しない) | AMD64 or IA64 | |
ProgramFiles | C:\Program Files | C:\Program Files (x86) | |
ProgramFiles(x86) | C:\Program Files(x86) | C:\Program Files (x86) | |
ProgramW6432 | C:\Program Files | C:\Program Files | |
CommonProgramFiles | %ProgramFiles%\Common Files | %ProgramFiles%\Common Files | |
CommonProgramFiles(x86) | %ProgramFiles(x86)%\Common Files | %ProgramFiles(x86)%\Common Files | |
CommonProgramW6432 | %ProgramW6432%\Common Files | %ProgramW6432%\Common Files |
Windows 7 RC x64ではどのプロセスもPROCESSOR_ARCHITEW6432を持たず、PROCESSOR_ARCHITECTUREがネイティブのアーキテクチャを示す値を持っていた。PROCESSOR_ARCHITEW6432は廃止されたかもしれない。
レジストリリダイレクションとレジストリリフレクション
WOW64は32ビットアプリケーションと64ビットアプリケーションの間で起こりうるレジストリの衝突を回避するために、32ビットアプリケーションからの一部のレジストリキーへのアクセスを、本来とは別の場所に分離する。この仕組みをレジストリリダイレクションといい、以下のキーに適用される。
- HKEY_LOCAL_MACHINE\Software
- HKEY_USERS\*\Software\Classes
- HKEY_USERS\*_Classes
また、リダイレクションにより64ビットアプリケーションとは違う場所に加えられた変更を、本来の場所にも反映させ、適切に同期を図る仕組みをレジストリリフレクションという。この仕組みは以下のキーに適用される。
- HKEY_LOCAL_MACHINE\Software\Classes
- HKEY_LOCAL_MACHINE\Software\Microsoft\COM3
- HKEY_LOCAL_MACHINE\Software\Microsoft\EventSystem
- HKEY_LOCAL_MACHINE\Software\Microsoft\Ole
- HKEY_LOCAL_MACHINE\Software\Microsoft\Rpc
- HKEY_USERS\*\Software\Classes
- HKEY_USERS\*_Classes
たとえば、32ビットアプリケーションがHKEY_LOCAL_MACHINE\Softwareにアクセスしようとした時、レジストリリダイレクションにより自動的にHKEY_LOCAL_MACHINE\Software\Wow6432Nodeへのアクセスに置き換えられる。
また、32ビットアプリケーションからHKEY_LOCAL_MACHINE\Software\Classesへの参照は、HKEY_LOCAL_MACHINE\Software\Wow6432Node\Classesへリダイレクトされるのではなく、レジストリリフレクションによりHKEY_LOCAL_MACHINE\Software\Classesへの参照となり、32ビット、64ビット両方のアプリケーションから同一の実体を参照することができるようになる。
画像はHKEY_LOCAL_MACHINE\Softwareにおけるリダイレクションの様子である。
以下はレジストリリフレクションの動作である。たとえば一方のビュー(32ビットレジストリビュー)にキーが作成されたら、他方のビュー(64ビットレジストリビュー)にもキーが作成される。すでに存在するキーに値を設定した場合、他方のキーにも値がコピーされる。
No | 32ビットレジストリビュー | 64ビットレジストリビュー |
---|---|---|
1 | 32ビットアプリケーションによるキーAの作成 | |
2 | (Reflection)キーAの作成 | |
3 | 64ビットアプリケーションによるキーAの値の変更 | |
4 | (Reflection)キーAの値が変化 | |
5 | 32ビットアプリケーションによるキーAの値の変更 | |
6 | (Reflection)キーAの値が変化 |
実際にリフレクションの結果が反映されるのは、ハンドルが閉じられた時である。また、その結果は "最後に書いたもの勝ち" であり最後の更新の結果が、最終的に反映される。
レジストリリフレクションの廃止
このような仕組みをもってしても、レジストリキーの衝突が起こりえたため、Windows 7と2008 R2以降はレジストリリフレクションの仕組みはほぼ削除されている。以下のキーにおけるリフレクションは削除された。
- HKEY_LOCAL_MACHINE\Software\Classes
- HKEY_LOCAL_MACHINE\Software\Microsoft\COM3
- HKEY_LOCAL_MACHINE\Software\Microsoft\EventSystem
- HKEY_LOCAL_MACHINE\Software\Microsoft\Ole
- HKEY_LOCAL_MACHINE\Software\Microsoft\Rpc
- HKEY_USERS\*\Software\Classes
- HKEY_USERS\*_Classes
ただし、CLSIDとInterfaceに関する以下のキーは依然としてリフレクションの対象である。
- HKEY_LOCAL_MACHINE\Software\Classes\CLSID
- HKEY_LOCAL_MACHINE\Software\Classes\Interface
- HKEY_USERS\*\Software\Classes\CLSID
- HKEY_USERS\*\Software\Classes\Interface
- HKEY_USERS\*_Classes\CLSID
- HKEY_USERS\*_Classes\Interface
リフレクションに依存していたアプリケーションは、いずれかを行うべきである。
- 明示的に別々のキーを使う。
- リフレクションの対象範囲外のレジストリキーを使う。
- リフレクションされるキーのために両方のビューを確認する。