64bit プロセス判定

IsWow64Process はWOW64か否かしか見ないため、次のような結果を返す。

OS 32 64 64
Process 32 32 64
結果 FALSE TRUE FALSE

よって実行環境をGetNativeSystemInfo*1で調べて、64bitだった場合IsWow64Processを使う。

// 指定したプロセスがx86x64アーキテクチャのどちらで動いているか調査
// 調査に成功した場合関数はTRUEを返し、is64bitsの値を更新する
// どちらか判断できない場合関数はFALSEを返す
BOOL Check64bitProcess(__in  DWORD pid,      // 調査対象のプロセスID
                       __out BOOL* is64bits) // 調査結果を受け取るポインタ(x64ならTRUE、x86ならFALSE)
{
  _ASSERTE(is64bits && "NULLだめ");

  // 最小権限でプロセスを開き、PIDの確認を行う
  OSVERSIONINFO osv;
  osv.dwOSVersionInfoSize = sizeof(osv);
  DWORD access = (::GetVersionEx(&osv) && osv.dwMajorVersion >= 6) ? PROCESS_QUERY_LIMITED_INFORMATION
                                                                   : PROCESS_QUERY_INFORMATION;
  if (!::CloseHandle(::OpenProcess(access, FALSE, pid)))
  {
    // 指定されたプロセスは存在しない
    return FALSE;
  }

  // 確認用関数を拾ってくる
  typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS)(HANDLE hProcess, PBOOL Wow64Process);
  static LPFN_ISWOW64PROCESS IsWow64Process = (LPFN_ISWOW64PROCESS)::GetProcAddress(
    ::GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");

  typedef void (WINAPI *LPFN_GETNATIVESYSTEMINFO)(LPSYSTEM_INFO lpSystemInfo);
  static LPFN_GETNATIVESYSTEMINFO GetNativeSystemInfo = (LPFN_GETNATIVESYSTEMINFO)::GetProcAddress(
    ::GetModuleHandle(_T("kernel32.dll")), "GetNativeSystemInfo");

  if (!IsWow64Process || !GetNativeSystemInfo)
  {
    // WOW64対応関数をエクスポートしていないバージョンのWindowsでは64bitプロセスはありえない
    *is64bits = FALSE;
    return TRUE;
  }

  SYSTEM_INFO sysinfo;
  GetNativeSystemInfo(&sysinfo);
  if (sysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
  {
    // x64アーキテクチャのため、WOW64チェック
    HANDLE process = ::OpenProcess(access, FALSE, pid);
    if (!process)
    {
      return FALSE;
    }
    BOOL success = IsWow64Process(process, is64bits);
    ::CloseHandle(process);
    *is64bits = !(*is64bits); // iswow64 == TRUE == 32bits process
    return success;
  }
  else if (sysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
  {
    // x86アーキテクチャで動くWindowsでは64bitプロセスはありえない
    *is64bits = FALSE;
    return TRUE;
  }
  else
  {
    // CPUアーキテクチャが不明。関数はとりあえず失敗する
    return FALSE;
  }
}


コメントの "最小権限で〜〜" のくだりは無くてもいい。そうすると状況によってはPIDが不正値でも「32bitプロセスだよ!」って言ってくるが。
あと権限も常にPROCESS_QUERY_INFORMATIONだけでいいかもね。PROCESS_QUERY_INFORMATIONだとProtected Processのハンドルが取得できなくて失敗するようになっちゃうけど。

*1:GetSystemInfoはWOW64上ではx86を返すため適当でない。