IWbemProviderInit
COM公式ドキュメント
IWbemProviderInit インターフェイスは、プロバイダーを初期化するために Windows Management から呼び出されます。すべてのプロバイダーは IWbemProviderInit を実装する必要があります。
メソッド 1
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
クライアント要求を受け取れるようにプロバイダーを初期化するために、Windows Management から呼び出されます。すべての種類のプロバイダーがこのメソッドを実装する必要があります。
| wszUser | LPWSTR | in | このプロバイダーの __Win32Provider 登録インスタンスでユーザーごとの初期化が要求されている場合は、ユーザー名へのポインター。それ以外の場合は NULL です。 イベントコンシューマープロバイダーの場合、そのプロバイダーの __Win32Provider インスタンスの PerUserInitialization プロパティの値にかかわらず、このパラメーターは NULL に設定されることに注意してください。 |
| lFlags | INT | in | 予約済みです。このパラメーターは 0 (ゼロ) である必要があります。 |
| wszNamespace | LPWSTR | in | プロバイダーが初期化される対象の名前空間名。 |
| wszLocale | LPWSTR | in | プロバイダーが初期化される対象のロケール名。 次の形式の文字列で、16 進値は Microsoft 標準の LCID 値です。
|
| pNamespace | IWbemServices* | in | Windows Management に戻るための IWbemServices ポインター。このポインターは、プロバイダーが行うあらゆる要求を処理できます。実行中に Windows Management を呼び出し返す場合、プロバイダーはこのポインターに対して IWbemProviderInit::AddRef メソッドを使用する必要があります。 |
| pCtx | IWbemContext* | in | 初期化に関連付けられた IWbemContext ポインター。このパラメーターは NULL の場合があります。 初期化を完了する前に Windows Management に対して要求を行う場合、プロバイダーはこのポインターに対して IWbemProviderInit::AddRef メソッドを使用する必要があります。詳細については、 Making Calls to WMI を参照してください。 プロバイダーが別のプロバイダーに対して依存要求を行う必要がある場合、ロックアップの可能性を避けるため、このコンテキスト文字列を WMI に渡し返す必要があります。ただし、独立した要求の場合はこれは不要であり、WMI がそのための新しいコンテキスト文字列を生成します。 |
| pInitSink | IWbemProviderInitSink* | in | プロバイダーが初期化状態を報告するために使用する IWbemProviderInitSink ポインター。 |
戻り値
プロバイダーは WBEM_S_NO_ERROR を返し、pInitSink パラメーターで指定されたオブジェクトシンクを使用してその状態を示す必要があります。ただし、プロバイダーが WBEM_E_FAILED を返し、シンクを使用しなかった場合、プロバイダーの初期化は失敗したものと見なされます。
解説(Remarks)
通常、プロバイダーは多重継承を使用して COM オブジェクトを実装し、 IWbemProviderInit インターフェイスと、 IWbemServices や IWbemEventProvider などの主要インターフェイスの両方をサポートします。
初期化状態は IWbemProviderInitSink::SetStatus を呼び出して報告します。必要に応じて、このメソッドを繰り返し呼び出して段階的に状態を報告できます。プロバイダーは、このポインターを使用して Windows Management に状態を伝える前に、その IWbemProviderInit::AddRef メソッドを呼び出して参照カウントをインクリメントする必要があります。
プロバイダーは、次のコード例のように IWbemProviderInitSink ポインターを同期的に使用できます。
HRESULT SampleProvider::Initialize(
/* [unique][in] */ LPWSTR wszUser,
/* [in] */ LONG lFlags,
/* [in] */ LPWSTR wszNamespace,
/* [unique][in] */ LPWSTR wszLocale,
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink
)
{
// Use AddRef on the pNamespace pointer, if required.
// Analyze other parameters.
// Tell Windows Management that you are initialized.
pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
return WBEM_S_NO_ERROR;
}
また、プロバイダーはポインターに対して AddRef メソッドを使用し、初期化を完了するための別のスレッドを作成して、呼び出しから直ちに戻ることもできます。
一部のプロバイダーの初期化処理では、WMI を呼び出し返すことがあります。WMI を呼び出し返し、その呼び出しの完了を待つ必要があるプロバイダーを依存プロバイダーと呼びます。同様に、WMI への呼び出しを依存要求と呼びます。 Initialize を実装する際、WMI は依存プロバイダーが次の規則に従うことを要求します。
-
依存要求では、WMI が
Initialize に渡した
IWbemContext ポインターを再利用する必要があります。
つまり、初期化中に行う WMI への呼び出しでは、WMI から渡された IWbemContext ポインターを再利用する必要があります。これを怠るとデッドロックが発生する可能性があります。
- 依存しない要求では、 IWbemContext ポインターを再利用してはなりません。
-
依存プロバイダーは、次の 2 つの方法のいずれかを使用して WMI に要求を行う必要があります。
- WMI から受け取ったスレッドで依存要求を行う。
- プロバイダーが作成した新しいスレッドで依存要求を行う。
- すべてのプロバイダーは、WMI から受け取ったスレッドを返却する必要があります。
-
WMI は、いかなる場合もプロバイダーが WMI から受け取ったスレッドをブロックすることを許可しません。
WMI から渡されたスレッドを慎重に扱わない場合の危険性は、プロバイダーが WMI スレッドプール内のすべてのスレッドを取得し、それらのスレッドをブロックしてしまう可能性があることです。これはシステムのデッドロックを招きます。
次のコード例は、そのような呼び出しで CLSID_WbemAdministrativeLocator 識別子を使用する方法を示しています。
IWbemLocator *pLoc = 0;
DWORD dwRes = CoCreateInstance(CLSID_WbemAdministrativeLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
CLSID_WbemAdministrativeLocator 識別子を使用しない場合、アクセス拒否エラーが発生します。WMI への接続の詳細については、 Creating a WMI Application or Script を参照してください。
例
次のコード例は、イベントコンシューマープロバイダー向けに Initialize を実装する方法を示しています。
HRESULT CMyEventConsumer::Initialize(
/* [in] */ LPWSTR pszUser,
/* [in] */ LONG lFlags,
/* [in] */ LPWSTR pszNamespace,
/* [in] */ LPWSTR pszLocale,
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink
)
{
pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
// Optionally, examine the namespace, locale, and so on
// being used.
return WBEM_S_NO_ERROR;
}
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IWbemProviderInit "{1BE41572-91DD-11D1-AEB2-00C04FB68820}"
#usecom global IWbemProviderInit IID_IWbemProviderInit "{}"
#comfunc global IWbemProviderInit_Initialize 3 wstr,int,wstr,wstr,sptr,sptr,sptr
; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。
; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。
; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。