Windows SDKが提供する.libファイルには関数群を提供するもの、単一.dllへの参照を提供するものがありますが、複数.dllへの参照を提供するものがあることは意外と知られていません。
今日はそういった複数の.dllへの参照を提供する.libの中でも代表的なOneCoreシリーズとMinCoreシリーズについて私の持つ知見を紹介しようと思います。
※これらは私が独自に調査蒐集した情報であり、公式の動作を保証するものではありません。
忙しい人向け要約
- OneCoreは1つリンクすれば全てOKなオールインワン.lib
- OneCore_downlevel.lib
- version.dllなどのオールドスタイル.dllへリンク
- OneCore_apiset.lib
- api-ms-win-core-version-l1-1-0.dllなどAPI Setsへのリンク
- OneCore.lib
- 可能な限りオールドスタイルだがAPI SetsにしかないものはAPI Setsでリンク
- OneCore_downlevel.lib
- MinCoreは限定環境向けAPI Sets提供.lib
- MinCore_downlevel.lib
- Windows7など極限制限下向け
- MinCore.lib
- Windows8.1やWIndowsPEなどの環境向け
- MinCore_downlevel.lib
前提知識:API Setsとは
Windows7から入った「OSのAPI群を厳格な名前空間に再配置したもの」及び「それらの名前から実体へリンクするライブラリローダー」です。
例えばGetFileVersionInfoExWはAPI Sets上はapi-ms-win-core-version-l1-1-0.dllにより提供されており、実行時に適切な.dll(環境によりversion.dllだったりKernelBase.dllなど)にリンクされ実行されます。
Windows10においては旧来のWin32APIと呼ばれていたものは全てカバーされており、旧来の.dllにリンクせずともほぼすべてのアプリを実装することが出来ます。
とはいえそれはWIndows10の話であり、Windows8.1やWindows7ではAPI Setsのカバー範囲が狭いため、それらのOSでの動作も必要な場合はまだ安易に利用できる状態ではありません。
またライブラリローダー自体が別系統であるため、DLLプリロード攻撃などに対しても耐性があります。
公式には旧来の方式に比べメモリー使用量が削減されることもあると説明されています。
OneCoreとは
API関係で数ある.libをすべてまとめたオールインワンな.libです。
具体的にはOneCore系の.libにさえリンクしておけばOS提供のAPI群は全て使用することが出来ます。
もちろんリンク時に必要なAPIのみ参照する方式なのでexeサイズの肥大化なども特にありません。
ただしAPI Setsの使用有無で若干のバリエーションがあります。
OneCore_downlevel.lib
旧来の.dllで提供できるAPIだけに絞ったOneCoreで、リンクされる.dllも全て旧来の.dllになります。
主にWindows7/8.1などの古い環境でも動作するアプリを作る開発者向けです。
当然ですが API Setsでのみ提供される 最新のAPI群は使用できません(リンクエラーになります)
OneCore_apiset.lib
全てのAPIをAPI Setsで提供するOneCoreです。
基本的にWindows10でしか動作しないようになりますが、全てのAPIを使用できDLLプリロード攻撃などに対しても耐性があります。
今はまだ遠い未来の話ですが、Windows10未満のOSがすべてサポート切れした後、MSはこれを使うことを主流としたいのだと予想されます。
WindowsSDKのバージョンが古い場合は提供されていないことがあります。
OneCore.lib
可能な限り旧来の.dllで提供し、それ以外はAPI Setsで提供するOneCoreです。
コード中で使用するAPIによって対象OSが変化してしまう問題があるため、私個人は使用を回避すべきだと考えます。
Windows10未満で動作する必要があればOneCore_downlevel.lib、Windows10でしか動作しなくてよいならOneCore_apiset.libの使用をお勧めします。
使用する場合は各APIのMSDNを良く参照の上、OSごとの動作確認をしっかり行うように注意してください。
また、WindowsSDKのバージョンが古いとOneCore_apiset.libと同じように動作することがあります。
MinCoreとは
旧来の.dllは環境(モバイルなど)により提供されないことがあります。
そういった環境でもAPI Setsは提供されるため、特殊環境向けにAPI Setsへリンクする.libが必要となりました、それがMinCoreです。
一般的な開発内の用途としてはWindows10未満向けでもAPI Setsを利用したい場合などがあげられます。
必要が無ければ基本的にはOneCoreを使うべきです。
MinCore_downlevel.lib
Windows7相当のAPI Setsを提供するMinCoreです。
これのみを使用してリンクエラーになっていないexeはWindows7上でも動作することが確約出来ます。
ただし提供されるAPI Setsはごく少量であるため(MSDN)あまり多くのことはできないでしょう。
具体的にこのMinCoreで動作が保証される特殊環境に何があるかは私は把握していません。
MinCore.lib
Windows8.1相当のAPI Setsを提供するMinCoreです。
ただ、実態調査をしたところWindows8.1では提供されていないAPI Setsへのリンクも提供されており実態が不明確です、可能なら使用は避けた方がよいでしょう。
提供されるAPI Setsはdownlevelに比べれば多彩ですがまだかなりの制限があると思うべきです(MSDN)
最低でもWindowsPEでMinCore.libの動作が保証されています(MSDN)
使い方
では実際に使ってみましょう。
要点は二つ、NODEFAULTLIBでkernel32.libとole32.libを外す、必要なOneCoreかMinCoreへのリンクを追加する、だけです。
もちろん手動で何かしらシステム.libへのリンクを追加しているなら撤去する必要があります。
では実際にやっていきましょう。
改造元として適当なC++プロジェクトを用意しました。
これはGetFileVersionInfoExWを使用していますがOneCoreもMinCoreも利用していないので、ビルドしてdumpbinすると以下のようにversion.dllへの参照がついています。
では改造していきましょう。
まず従来のlibと同時に使用すると正しく適用できないため外します。
ここを
こう消します。
さらに一部は暗黙でリンクされるので追加で除外設定を入れます。
そしてリンクする.libを変更します(今回はわかりやすくOneCore_apiset.lib
無事api-ms-win-core-version-l1-1-0.dllを参照する形に変わりました。
※OneCore_downlevel.libかOneCore.libの場合version.dllのままとなります。
今回はコード中からOneCore_apiset.libのリンク指示を入れましたが、プロジェクトプロパティの追加の依存ファイルでももちろん問題はありません。
終わりに
今回はOneCore/MinCoreについてある程度知見を広めることを目的とした記事でした。
巷では不親切なドキュメントのせいで誤ってリンクしてしまい問題になるケースも多く、そういった悲劇を少しでも減らしたいという思いもあります。
自分自身OneCoreやMinCoreに思うところがないではないですが、OneCoreの煩雑なリンク作業の手間を軽減しようとする試み自体は良いことだと思います。
ではまた次の記事で。