MicrosoftがGitHubでMITライセンス公開しているWILのGitHub Wikiの記事を和訳・改変したものです。素人による翻訳なので、誤訳や著作権上の問題などありましたらご連絡いただけますと幸いです。
Win32ヘルパー(原題:Win32 helpers)
Brian Gianforcaro、2020/10/6、リビジョン9個
WILのWin32ヘルパーはWin32で使われる多様な関数とデータ型を補助します。
使い方
Win32ヘルパーは適切なヘッダーファイルをインクルードして使用できます。
#include <wil/win32_helpers.h>
文字列長定数
すべての文字列長定数はwil
名前空間にありsize_t
型です。
名前 | 値 | 意味 |
---|---|---|
max_path_segment_length |
254 | ディレクトリ名やファイル名の最大長。終端のnullは含みません。 |
max_path_length |
259 | MAX_PATH パスの最大長。終端のnullは含みません。 |
max_extended_path_length |
32743 | 拡張パス(extended path)の最大長。終端のnullは含みません。 |
guid_string_buffer_length |
39 | GUIDを保持するバッファーのサイズ。前後の中括弧と終端のnullを含みます。 |
guid_string_length |
38 | GUID文字列の長さ。前後の中括弧は含みますが、終端のnullは含みません。 |
max_extended_path_length
の一般的ではない値はシステム制限の0x7FFF
から24を引いた数です。24は\Device\HardDiskVolume#
プレフィックスの長さです。パスが10~99番目のハードディスクボリュームを指す場合、このプレフィックスは25文字に増え、対応する最大長は1だけ減ります。
ファイルタイム定数
ファイルタイム定数はwil::filetime_duration
名前空間にあります。これらはlomg long
型であり、よく知られた期間を持つFILETIME
単位(100 ns)の数を表します。
名前 | 値 |
---|---|
one_millisecond |
10000 |
one_second |
10000000 |
one_minute |
600000000 |
one_hour |
36000000000 |
one_day |
864000000000 |
ファイルタイムヘルパー
ファイルタイムヘルパーはwil::filetime
名前空間にあります。
unsigned long long to_int64(const FILETIME &ft)
FILETIME from_int64(unsigned long long i64)
FILETIME
構造体(2つの32ビット整数)と64ビット符号なし整数の変換関数。
FILETIME add(_In_ FILETIME const &ft, long long delta)
- 既存の
FILETIME
構造体の値を特定の刻み(tick)で調整します。
- 既存の
bool is_empty(const FILETIME &ft)
FILETIME
全体が0
ならtrue
を返します。
FILETIME get_system_time()
- システム日時を
FILETIME
として返します。
- システム日時を
可変長文字列を返す関数
多くのWin32関数は呼び出し側の提供するバッファーに可変長文字列を返します。AdaptFixedSizeToAllocatedResult
テンプレート関数は文字列のバッファーを要求し、必要に応じてより大きなバッファーで再試行する共通パターンを実装します。
template<typename string_type, size_t stackBufferLength = 256> HRESULT AdaptFixedSizeToAllocatedResult(string_type& result, wistd::function<HRESULT(PWSTR, size_t, size_t*)> callback);
求める文字列を生産するまで、バッファーを大きくしながら繰り返しcallback
を呼び出します。バッファーはstring_type
形式で返されます。失敗時はCOMエラーコードを返し、result
は変更されません。
string_type
はstring_maker(原文リンク)のサポートする任意の型です。stackBufferLength
は初期クエリで使用されるスタックバッファーのサイズです。ほとんどの使用ケースで十分だろう値を選ぶことで、リトライが不要なより短い実行パスを提供できます。callback
は提供したバッファーに文字列を取得し、実際あるいは必要なサイズを返します。一般的にラムダ式が渡されます。
HRESULT callback(PWSTR value, size_t valueLength, size_t* valueLengthNeededWithNul);
value
は書き込まれるバッファーのポインタです。valueLength
はバッファーのサイズです。null終端を含めます。valueLengthNeededWithNul
はバッファーに要求されるサイズを取得します。null終端を含めます。
コールバックが文字列全体を読み込めた場合、valueLengthNeededWithNul
は返される文字列(null終端を含む)の正確なサイズを返し、コールバックはS_OK
を返します。
バッファーのサイズが小さすぎてコールバックが文字列全体を読み込めない場合、valueLengthNeededWithNul
は次の反復で使うバッファーのサイズを返し、コールバックはS_OK
を返します。多くの場合、ラップしたいWin32関数は次の反復の提案サイズを提供するでしょう。その他の場合、(std::max)(40, valueLength * 2)
のようなヒューリスティックを使う必要があり、整数のオーバーフロー回避に注意が必要です。
コールバックは文字列を取得できない場合にCOMエラーコードを返し、それはAdaptFixedSizeToAllocatedResult
の戻り値に伝播されます。この場合、valueLengthNeededWithNul
の値は使用されません。
ノート:AdaptFixedSizeToAllocatedResult
で使われる引数は一般的な文脈の命名規則(Length
はnull終端を除いた長さ、Size
はnull終端を含む長さ)に従いません。私達はこれを認識しています。
可変長文字列を返す関数の定義済みアダプター
HRESULT
を返す非throw
版アダプターが常に用意されています。throw
版はしばしば返された文字列をそのまま返します。
template<typename string_type, size_t stackBufferLength = 256> HRESULT ExpandEnvironmentStringsW(_In_ PCWSTR input, string_type& result) WI_NOEXCEPT; template<typename string_type = wil::unique_cotaskmem_string, size_t stackBufferLength = 256> string_type ExpandEnvironmentStringsW(_In_ PCWSTR input);
ExpandEnvironmentStringsW(input, buffer, bufferSize)
のラッパー。
template<typename string_type, size_t stackBufferLength = 256> HRESULT SearchPathW(_In_opt_ PCWSTR path, _In_ PCWSTR fileName, _In_opt_ PCWSTR extension, string_type& result) WI_NOEXCEPT; template<typename string_type = unique_cotaskmem_string, size_t stackBufferLength = 256> string_type TrySearchPathW(_In_opt_ PCWSTR path, _In_ PCWSTR fileName, PCWSTR _In_opt_ extension);
SearchPathW(path, fileName, extension, bufferSize, buffer, nullptr)
のラッパー。
TrySearchPathW
版はERROR_FILE_NOT_FOUND
を成功として扱い、空文字列を作成します。
template<typename string_type, size_t stackBufferLength = 256> HRESULT QueryFullProcessImageNameW(HANDLE processHandle, _In_ DWORD flags, string_type& result) WI_NOEXCEPT;
QueryFullProcessImageNameW(processHandle, flags, buffer, &bufferSize)
のラッパー。
template<typename string_type> HRESULT GetEnvironmentVariableW(_In_ PCWSTR key, string_type& result) WI_NOEXCEPT; template<typename string_type = unique_cotaskmem_string> string_type GetEnvironmentVariableW(_In_ PCWSTR key); template<typename string_type> HRESULT TryGetEnvironmentVariableW(_In_ PCWSTR key, string_type& result) WI_NOEXCEPT; template<typename string_type = unique_cotaskmem_string> string_type TryGetEnvironmentVariableW(_In_ PCWSTR key);
GetEnvironmentVariableW(key, buffer, bufferSize)
のラッパー。
TryGetEnvironmentVariableW
版はERROR_ENVVAR_NOT_FOUND
を成功として扱い、空文字列を作成します。
template<typename string_type, size_t initialBufferLength = 128> HRESULT GetModuleFileNameExW(_In_opt_ HANDLE process, _In_opt_ HMODULE module, string_type& path); template <typename string_type = unique_cotaskmem_string> string_type GetModuleFileNameExW(HANDLE process, HMODULE module);
GetModuleFileNameExW(process, module, buffer, bufferSize)
のラッパー。
template<typename string_type, size_t initialBufferLength = 128> HRESULT GetModuleFileNameW(HMODULE module, string_type& path); template<typename string_type = unique_cotaskmem_string> string_type GetModuleFileNameW(HMODULE module); template<typename string_type = unique_cotaskmem_string> string_type GetModuleFileNameW(HMODULE module);
GetModuleFileNameExW(nullptr, module, buffer, bufferSize)
のラッパー。
template<typename string_type, size_t stackBufferLength = 256> HRESULT GetSystemDirectoryW(string_type& result) WI_NOEXCEPT;
GetSystemDirectoryW(buffer, bufferSize)
のラッパー。
ワンタイム初期化(One-time initialization)
ワンタイム初期化(one-time-initialization)ヘルパー関数は最初に呼び出されたときだけ実行され、その後の呼び出しでは何もしません。
template<typename T> HRESULT init_once_nothrow(_Inout_ INIT_ONCE& initOnce, T func, _Out_opt_ bool* callerCompleted = nullptr) WI_NOEXCEPT;
initOnce
はINIT_ONCE
構造体であり、初期化が既に実行されたかを記録します。func
はHRESULT operator()
メソッドを持つ関数(原文:functor)です。callerCompleted
はオプション引数です。提供された場合、func
の実行が成功した場合はtrue
、func
が実行されないか失敗した場合はfalse
を設定されます。
func
がCOM失敗コードを返した場合、失敗コードはinit_one_nothrow
の戻り値となり、initOne
は未初期化のままになります。同じinitOne
を与えたその後のinit_one_nothrow
呼び出しでは初期化が再試行されます。
使用例:
INIT_ONCE g_init{}; ComPtr<IFoo> g_foo; HRESULT MyMethod() { bool winner = false; RETURN_IF_FAILED(wil::init_once_nothrow(g_init, [] { ComPtr<IFoo> foo; RETURN_IF_FAILED(::CoCreateInstance(..., IID_PPV_ARGS(&foo)); RETURN_IF_FAILED(foo->Startup()); g_foo = foo; }, &winner); if (winner) { RETURN_IF_FAILED(g_foo->Another()); } return S_OK; }
詳細はInitOnceExecuteOnce on MSDNを参照してください。
template<typename T> bool init_once_failfast(_Inout_ INIT_ONCE& initOnce, T&& func) WI_NOEXCEPT;
_failfast
版はcallerCompleted
の値を返し、初期化関数の失敗時はフェイルファストします。
template<typename T> bool init_once(_Inout_ INIT_ONCE& initOnce, T func);
例外ベース版のため、func
はvoid operator()
を持つべきです。これは例外のthrow
により失敗を報告します。
使用例:
INIT_ONCE g_init{}; ComPtr<IFoo> g_foo; void MyMethod() { bool winner = wil::init_once(g_init, [] { ComPtr<IFoo> foo; THROW_IF_FAILED(::CoCreateInstance(..., IID_PPV_ARGS(&foo)); THROW_IF_FAILED(foo->Startup()); g_foo = foo; }); if (winner) { THROW_IF_FAILED(g_foo->Another()); } } bool init_once_initialized(_Inout_ INIT_ONCE& initOnce) WI_NOEXCEPT;
initOne
構造体が初期化成功で完了した場合、true
が返されます。
その他のヘルパー関数
template<typename string_type, size_t stackBufferLength = 256> HRESULT ExpandEnvAndSearchPath(_In_ PCWSTR input, string_type& result) WI_NOEXCEPT;
ExpandEnvironmentStringsW
と続くSearchPathW
の組み合わせです。
HINSTANCE GetModuleInstanceHandle();
現在のモジュールのハンドルを返します。__ImageBase
特殊リンカーシンボルを使います。
auto GetProcAddressByFunctionDeclaration(hinst, FunctionName)
GetProcAddressByFunctionDeclaration
マクロは提供した関数の関数プロトタイプに合うように戻り値をキャストする型安全なGetProcAddress
です。
使用例:
auto sendMail = GetProcAddressByFunctionDeclaration(hinstMAPI, MAPISendMailW); if (sendMail) { sendMail(0, 0, pmm, MAPI_USE_DEFAULT, 0); }
著作権表示
この記事は以下の著作物を使用しています。
Copyright (c) Microsoft Corporation. All rights reserved. https://github.com/microsoft/wil/blob/master/LICENSE