何となく Blog by Jitta
Microsoft .NET 考

目次

Blog 利用状況
  • 投稿数 - 591
  • 記事 - 18
  • コメント - 2182
  • トラックバック - 183
ニュース
  • 検索エンジンで来られた方へ:
    お望みの情報は見つかりましたか? よろしければ、コメント欄にどのような情報を探していたのか、ご記入ください。
It's ME!
  • はなおか じった
  • 世界遺産の近くに住んでます。
  • Microsoft MVP for Visual Developer ASP/ASP.NET 10, 2004 - 9, 2009
サイト内検索
広告

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

その他

わんくま同盟

同郷

 
書き直し

x64 環境なのかどうかの判定をする方法。

OS のバージョンを見ても、x64 なのかどうかはわかりません。例えば、32ビット版 Windows XP のバージョンは 5.1 ですが、64ビット版の場合は 5.2 になります。しかし、Windows Server 2003 も、5.2 です。なので、別の方法で調べます。

MSDN を調べると、IsWow64Process 関数(英語)が見つかります。しかし、「64ビット OS 上で動く64ビット アプリケーションの場合は、この関数は FALSE を返す」のだそうです。一応、それなりに作り込めば、32ビット アプリケーションと64ビット アプリケーションは、同じコードを共有できます。したがって、「WOW64 上で動いているか」をチェックするだけでは不完全な場合もあります。

ということで、まず、IsWow64Process 関数があるかどうかを調べ、なければ32ビット OS 上で動く32ビット アプリケーション。関数が存在し、TRUE を返せば64ビット OS 上で動く32ビット アプリケーション。FALSE を返せば、さらに何らかの調査をして、64ビット OS 上で動く64ビット アプリケーションなのか、32ビット OS 上で動く32ビット アプリケーションなのか、という判別を行います。

それはなに?と調べると、GetSystemInfo 関数(英語)を使えば良さそうです。SYSTEM_INFO 構造体(英語)の、wProcessorArchitecture で判別すれば良さそうです。

なお、この関数は、IsWow64Process 関数とセットで使う必要がありそうです。WOW64 上で動いている場合、32ビットだと返事をしそうだからです。WOW64 上で動作している場合に、ベースとなる OS が64ビットなのかどうかを知るには、GetNativeSystemInfo 関数(英語)を使います。なお、GetNativeSystemInfo 関数は、WOW64 上でなければ GetSystemInfo 関数と同等であると書かれていますので、とりあえずこちらを使ってもいいかもしれません。その場合、存在チェックが必要かと思われます。


ビルドできることのみ確認しています。


#include <windows.h>

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
typedef void (WINAPI *LPFN_GETNATIVESYSTEMINFO) (LPSYSTEM_INFO);

typedef enum {
    UNKNOWN = 0
    , SYSINFO_32PROCESS = 1
    , SYSINFO_32PROCESS_ON_WO64 = 2
    , SYSINFO_64PROCESS = 3
} BaseSystemInfo;

BOOL Isx64Architecture(void)
{
    LPFN_GETNATIVESYSTEMINFO fnGetNativeSystemInfo;
    BOOL bIsx64 = FALSE;
    SYSTEM_INFO info;

    if (fnGetNativeSystemInfo == NULL) {
        fnGetNativeSystemInfo = (LPFN_GETNATIVESYSTEMINFO) GetProcAddress(
            GetModuleHandle(TEXT("kernel32")), TEXT("GetNativeSystemInfo"));
    }

    if (fnGetNativeSystemInfo != NULL) {
        fnGetNativeSystemInfo(&info);
        if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
            bIsx64 = TRUE;
        } else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
            bIsx64 = TRUE;
        } else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
            bIsx64 = FALSE;
        }
    }
    return bIsx64;
}

BOOL IsWow64(HANDLE processHandle)
{
    LPFN_ISWOW64PROCESS fnIsWow64Process;
    BOOL bIsWow64 = FALSE;

    if (fnIsWow64Process == NULL) {
        fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
            GetModuleHandle(TEXT("kernel32")), TEXT("IsWow64Process"));
    }

    if (fnIsWow64Process != NULL) {
        if (!fnIsWow64Process(processHandle, &bIsWow64)) {
            return FALSE;
        }
    }
    return bIsWow64;
}

BaseSystemInfo GetBaseSystemInfo(HANDLE processHandle)
{
    if (IsWow64(processHandle) == FALSE) {
        return SYSINFO_32PROCESS;
    } else if (Isx64Architecture() == TRUE) {
        return SYSINFO_64PROCESS;
    } else {
        return SYSINFO_32PROCESS_ON_WO64;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    switch (GetBaseSystemInfo(GetCurrentProcess())) {
        case SYSINFO_32PROCESS_ON_WO64:
            printf("WOW64");
            break;
        case SYSINFO_64PROCESS:
            printf("x64");
            break;
        case SYSINFO_32PROCESS:
            printf("x86");
            break;
    }
    return 0;
}
投稿日時 : 2007年12月26日 22:39
コメント
  • # re: [Windows API] x64判定
    ちゃっぴ
    Posted @ 2007/12/27 0:46
    > 例えば、32ビット版 Windows XP のバージョンは 5.1 ですが、64ビット版の場合は 5.2 になります。しかし、Windows Server 2003 も、5.2 です。なので、別の方法で調べます。

    Windows XP x64 と Windows Server 2003 x64 は同じ kernel 使ってますからね。Windows XP 32bit とは別。
  • # re: [Windows API] x64判定
    ちゃっぴ
    Posted @ 2007/12/27 0:55
    ん、よく見たら wProcessorArchitecture で判別?
    それって、AMD64 とか EM64T に対応している CPU の場合、32bit OS つかっていても true になりそうな。
  • # re: [Windows API] x64判定
    ちゃっぴ
    Posted @ 2007/12/27 1:12
    Unicode build すると GetProcAddress で compile error 発生しますね。VS2005

    第二引数が LPCSTR なので。
    TEXT macro はずすと compile 通ります。
  • # re: [Windows API] x64判定
    ちゃっぴ
    Posted @ 2007/12/27 1:18
    Compile は通ったけど、うまく動かないようです。
    後日調査してみます。

    Vista の application 設計指針にここら辺無かったかな?
  • # re: [Windows API] x64判定
    ちゃっぴ
    Posted @ 2007/12/27 1:23
    あ、単純な初期化漏れか。。。

    LPFN_GETNATIVESYSTEMINFO fnGetNativeSystemInfo = NULL;

    LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;

    にする必要がありますね。VS2005
  • # re: [Windows API] x64判定
    ちゃっぴ
    Posted @ 2007/12/27 1:50
    Windows Server 2003 R2 x64 SP2 で検証しましたけど、WOW64 かどうかに関わらず x64 を返しますね。

    Vista 32bit でも検証しましたがこちらは x86 を返します。

    ところで、Windows Server 2003 R2 64bit は C++ の runtime 無くても動いたのに Vista 32bit では必要だったのはなぜ?
  • # re: [Windows API] x64判定
    Jitta
    Posted @ 2007/12/27 7:46
    ちゃっぴさん、検証ありがとうございます。

    x64へのビルドって、VS2005でできました?
    WDK にはコンパイル環境がありますが、Platform の方はスイッチだけでええのだろうか?
  • # re: [Windows API] x64判定
    ちゃっぴ
    Posted @ 2007/12/28 2:24
    64bit で compile して動かしたら結果が x86 でした。orz

    Linker の詳細で対象コンピュータを x64 にしてやれば OK でっせ。

    事前に SDK の path 通しておく必要ありますが。

    あと、x64 では support されていない compile option があって LNK1112 とか発生します。

    Win32 ではなく新しい platform で定義してやったほうがいですね。
  • # re: [Windows API] x64判定
    ちゃっぴ
    Posted @ 2007/12/28 2:27
    <結果>
    x86 では x86
    wow64 では x64
    x64 では x86
  • # re: [Windows API] x64判定
    Jitta
    Posted @ 2007/12/28 7:46
    GetBaseSystemInfo の判定式が間違ってますね。
    昨日、動きまで確認したのを作ったのだが、家に帰ると問題が発生してて、PCさわれなかった...

    if (iswow64) {
    //wow64
    } else {
    if (isx64) {
    // x64
    } else {
    // x86
    }
    }
タイトル  
名前  
Url
コメント