-- 追記ここから --
タイトルに書いている通りここにXPで動かす方法は置いていない
下を読む必要はないからこっちに行け
VisualStudio11作成アプリをWinXP上で動作させるHACK
-- 追記ここまで --
本題に入る前になぜ新しいVC++で作った実行ファイルが古いWindowsで動かなくなるのかの説明を
このへんちゃんと説明してるページが無いように感じたから
基本は2点
・リンカが設定するサブシステムバージョンが実行するWindowsよりも上
・リンクされるランタイムライブラリが実行するWindowsに無いAPIを読んでいる
まず前者
実行ファイルのヘッダには要求するサブシステムバージョンを設定するフィールドがあって
if ( Windows自身のメジャーバージョン > 実行ファイルが要求するメジャーバージョン || Windows自身のメジャーバージョン == 実行ファイルが要求するメジャーバージョン && Windows自身のマイナーバージョン >= 実行ファイルが要求するマイナーバージョン )
実行を許可
else
実行を拒否
みたいに要求されているバージョンを満たしているかチェックしてる
XPだとメジャー = 5、マイナー = 1、よく耳にする5.1とかそのままの理解でおk
NT 3.1が実はマイナー = 0xA(10)なのはトリビア
で実行ファイルに設定されるほうはVC++2008なら5.0、2010なら5.1のように設定される
(APIの話は置いといて)VC++2010で作った実行ファイルはWindows 2000では5.0 < 5.1なので実行できなくなる
IMAGE_OPTIONAL_HEADER structure
チェックされるのはMajorSubsystemVersion/MinorSubsystemVersionの方でMajorOperatingSystemVersion/MinorOperatingSystemVersionやMajorImageVersion/MinorImageVersionは一切チェックされないので注意。
解決法は書き換えるだけ
ファイルに設定されているだけだから
以前言った通りVC++2010なら規定では5.1に設定するけど明示的に5.0を指定することは可能
残念ながらVC++11では6.0よりも小さい値を指定することはできなくなったのでバイナリエディタでも使えばいいんじゃないですかね
APIの話に比べたら簡単なもんです
で、後者のAPI
俺Windows 2000で使えないAPI呼び出してないよ?ちゃんとGetProcAddress使ってるよ?という人は下のページを読んでくることをお勧めする
exeファイルとCRT
VC++付属のランタイムライブラリを使用しないというのはこの暗黙に呼び出されるAPIを無くすのが目的
VC++付属のものではなくDDK/WDKに入ってるものを使用するという手法も古いWindowsには無いAPIを呼び出していないランライムに差し替えることが目的
ただランタイムを使わないってのにも当然デメリットがあって
・C言語由来のものが使えない
・C++由来のものが使えない
・スタートアップコードが無いのでmainやWinMainの引数をだれも用意してくれない
・/GSが使えない(bufferoverflowU.libで代用可)
・__try、__except、__finallyが使えない(SEHはWindowsの機構ではあるがこれらのキーワードはVC++が用意してくれているラッパー)
・SafeSEH用のMagic sectionがランタイムライブラリの中(自分で用意すれば代用可)
ぱっと思いつくだけでもこんだけ
WDK/DDKのもので代用してもデバイスドライバやWindowsのコア部分用に作られているのでstd::vectorすら使えなくなる
ベターCですら辛いかもね
そうなるとランタイムライブラリはVC++付属のものを使って使えないAPIだけ挿げ替えたくなるのもわかるでしょう?
で、APIだけ挿げ替える方法が
こことか
こことか
こことか
こことか になるわけ
本題
上で言った通りサブシステムバージョンが6.0なのは自分で何とかしてください
APIに関してはXPで使えないのはGetTickCount64、LCMapStringEx、FlsAlloc、FlsSetValue、FlsGetValue、FlsFree
ランタイムを静的リンクするようにしてこれとこれを
.asmのコンパイル方法はいつも通りこの辺
技術的に出てきそうな疑問
Q. GetTickCount64をGetTickCountに置き換えて大丈夫なのか?
A. 時間を取得する用途ではなくGS Cookieの初期化の為の予測困難な値の取得に使用しているのでまともな値に補正する必要性は無いと考えた
Q. LCMapStringExをLCMapStringWに置き換えて大丈夫なのか?
A. 大丈夫じゃねーの?(根拠無し)
Q. Fls APIをTls APIに置き換えて大丈夫なのか?
A. 大丈夫だろう
リソースリークが問題になるような所に保証も何もないこんなもん使用すべきじゃない
VC++がTlsからFlsに移った経緯でも調べておけ
Q. なんでVC2003〜2010のようにFlsが使用可能ならFlsを使うようにしないの?
A. めんどい
Q. 静的じゃないとだめなの?
A. 動的だとDLLを差し替えることになる
大変めんどい
他にも4つぐらいAPI使ってたけどなんかそこまでして動かす価値があるかなぁって思い始めた
localeめんどくせえわ
気が向いたら続きやるかもね