読者です 読者をやめる 読者になる 読者になる

WOW64のファイルシステムのリダイレクトをOFFにする

会社で、WiXを使って、とあるプロジェクトのインストーラを作っているのですが、ほとんどは.NETなものの、一部のコードだけ、ドライバに依存するため、64bit対応するに当たって、system32(system64ではないんだなこれが。)にファイルをコピーしないといけません(プログラム自体は、32bitなので、32bit/64bit兼用のインストーラ)。

本来なら、%windir%\Sysnativeにファイルをコピーすれば、リダイレクトの影響を受けずにファイルをコピーできるはずなんですが、なぜか、sysnativeがちゃんと動きません。普通にsystem32にファイルをコピーすればsyswow64にリダイレクトされるので、八方塞がりです。
仕方がないので、カスタムアクションで、ファイルをコピーするという暴挙に出ることにしました。仕方がありません。下のコードは、WOW64のリダイレクトを一時的にOFFにするコード。

class Wow64RedirDisabler
{
public:
  Wow64RedirDisabler()
  {
    HINSTANCE hKrnl32 = GetModuleHandle(_T("kernel32"));
    m_disable = (LPFN_WOW64Disable)
      ::GetProcAddress(hKrnl32, "Wow64DisableWow64FsRedirection");
    m_revert = (LPFN_WOW64Revert)
      ::GetProcAddress(hKrnl32, "Wow64RevertWow64FsRedirection");
    
    if(m_disable)
      m_disablingWow64Redirection = m_disable(&m_val);
    else
      m_disablingWow64Redirection = FALSE;
  }

  ~Wow64RedirDisabler()
  {
    if(m_revert && m_disablingWow64Redirection)
      m_revert(m_val);
  }

private:
  typedef BOOL (WINAPI* LPFN_WOW64Disable)(PVOID*);
  typedef BOOL (WINAPI* LPFN_WOW64Revert)(PVOID);
  LPFN_WOW64Disable m_disable;
  LPFN_WOW64Revert m_revert;
  PVOID m_val;
  BOOL m_disablingWow64Redirection;
};

system32のパス自体は、

TCHAR sys32[MAX_PATH];
SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, sys32);

で取得できます。APIが微妙に古いのはWindows 2000も対応しないといけないため。おもしろいことに(?)、このAPIは、WOW64下でも、%windir%\system32のパスを返します。完全にリダイレクトに頼りきりなんですね。まぁ、逆に言えば、このAPIがsyswow64を返したぐらいで、32bitのプログラムが全部動くような理想的な世界だったら、WOW64のリダイレクションなんていらなかったのかもしれませんけど、微妙に矛盾を感じます。