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と協調して動作する。

  1. 32ビットアプリケーションが動作するとき、まずネイティブライブラリローダーが動作する。
    • そのイメージファイルが正しい32ビット形式なら、ローダーは特別にWOW64環境を構築する。
  2. wow64.dllは32ビット版のntdll.dllをロードし、初期化コードを実行する。
  3. 次に必要な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


リフレクションに依存していたアプリケーションは、いずれかを行うべきである。

  1. 明示的に別々のキーを使う。
  2. リフレクションの対象範囲外のレジストリキーを使う。
  3. リフレクションされるキーのために両方のビューを確認する。