IFunctionDiscoveryNotification
COM公式ドキュメント
このインターフェイスは、非同期クエリをサポートするためにクライアントプログラムによって実装され、クエリパラメーターに一致する関数インスタンスが追加または削除されたときにクライアントプログラムに通知するために Function Discovery によって呼び出されます。
解説(Remarks)
Function Discovery から通知を受け取るには、クライアントプログラムがこのインターフェイスを実装する必要があります。クライアントプログラムの実装のアドレスをいずれかのクエリメソッドに渡すことで、クエリパラメーターに一致する関数インスタンスの通知が有効になります。
Function Discovery は、実際の通知を行うためにクライアントプログラムの IFunctionDiscoveryNotification::OnUpdate メソッドを呼び出します。この通知は、関数インスタンスが追加または削除されたときに生成されます。
例
個々のメソッドのページに掲載されている例は、次のクラス宣言に基づいています。
class CMyNotificationListener : public CFunctionDiscoveryNotificationWrapper
{
public:
CMyNotificationListener() {
m_hAddEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
m_hRemoveEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
m_hChangeEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
}
~CMyNotificationListener() {
CloseHandle( m_hAddEvent );
CloseHandle( m_hRemoveEvent );
CloseHandle( m_hChangeEvent );
}
private:
HANDLE m_hAddEvent, m_hRemoveEvent, m_hChangeEvent;
};
メソッド 3
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
関数インスタンスが追加、削除、または変更されたことを示します。
| enumQueryUpdateAction | QueryUpdateAction | in | 指定された関数インスタンスに対して Function Discovery が実行するアクションの種類を指定する QueryUpdateAction 値です。 |
| fdqcQueryContext | ULONGLONG | in | 変更通知のために登録されたコンテキストです。型 FDQUERYCONTEXT は DWORDLONG として定義されます。このパラメーターは NULL にできます。 |
| pIFunctionInstance | IFunctionInstance* | in | 更新の影響を受ける関数インスタンスを表す IFunctionInstance インターフェイスポインターです。 |
戻り値
クライアントプログラムによる OnUpdate メソッドの実装は、呼び出し元に次のいずれかの HRESULT 値を返す必要があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 入力パラメーターのいずれかの値が無効です。 |
解説(Remarks)
このメソッドからクエリオブジェクトに対して Release を呼び出さないでください。呼び出すとデッドロックが発生する可能性があります。コールバックの処理中に別のスレッドからクエリオブジェクトに対して Release が呼び出された場合、そのオブジェクトはコールバックが完了するまで解放されません。
プロバイダーによって Function Discovery に渡されるすべての通知はキューに格納され、クライアントへ 1 つずつ返されます。コールバックは同期されるため、クライアントが一度に受け取る通知は 1 つだけです。
他の IFunctionDiscoveryNotification メソッドの呼び出しが別のスレッドで行われる可能性があるため、呼び出し中にスレッドの状態に加えた変更は、メソッドを終了する前に元に戻す必要があります。
例
次のコードは OnUpdate ハンドラーの実装を示しています。CMyNotificationListener クラスは IFunctionDiscoveryNotification のトピックで定義されています。
#include <windows.h>
HRESULT STDMETHODCALLTYPE CMyNotificationListener::OnUpdate(
IN QueryUpdateAction Action,
IN FDQUERYCONTEXT fdqcQueryContext,
IN IFunctionInstance *pInstance)
{
HRESULT hr = S_OK;
switch (Action) {
case QUA_ADD:
SetEvent( m_hAddEvent );
break;
case QUA_REMOVE:
SetEvent( m_hRemoveEvent );
break;
case QUA_CHANGE:
SetEvent( m_hChangeEvent );
break;
}
return S_OK;
}
非同期クエリの処理中に発生したエラーを受け取ります。
| hr | HRESULT | in | 報告されるクエリエラーです。 |
| fdqcQueryContext | ULONGLONG | in | 変更通知のために登録されたコンテキストです。型 FDQUERYCONTEXT は DWORDLONG として定義されます。 |
| pszProvider | LPWSTR | in | プロバイダーの名前です。 |
戻り値
クライアントプログラムによる OnError メソッドの実装は、呼び出し元に次のいずれかの HRESULT 値を返す必要があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 入力パラメーターのいずれかの値が無効です。 |
解説(Remarks)
通常、クライアントは、非同期エラーはすべて致命的でありクエリが結果を返さなくなると想定しますが、カスタムプロバイダーのドキュメントでは特定のエラーコードについて別の動作が示されている場合があります。
このメソッドからクエリオブジェクトに対して Release を呼び出さないでください。呼び出すとデッドロックが発生する可能性があります。コールバックの処理中に別のスレッドからクエリオブジェクトに対して Release が呼び出された場合、そのオブジェクトはコールバックが完了するまで解放されません。
プロバイダーによって Function Discovery に渡されるすべての通知はキューに格納され、クライアントへ 1 つずつ返されます。コールバックは同期されるため、クライアントが一度に受け取る通知は 1 つだけです。
他の IFunctionDiscoveryNotification メソッドの呼び出しが別のスレッドで行われる可能性があるため、呼び出し中にスレッドの状態に加えた変更は、メソッドを終了する前に元に戻す必要があります。
通知中に発生した追加、削除、または更新の各イベントを受け取ります。
| dwEventID | DWORD | in | イベントの種類です。
| ||||||||||
| fdqcQueryContext | ULONGLONG | in | 変更通知のために登録されたコンテキストです。型 FDQUERYCONTEXT は DWORDLONG として定義されます。このパラメーターは NULL にできます。 | ||||||||||
| pszProvider | LPWSTR | in | プロバイダーの名前です。 |
戻り値
クライアントプログラムによる OnEvent メソッドの実装は、呼び出し元に次のいずれかの HRESULT 値を返す必要があります。
| リターンコード | 説明 |
|---|---|
| メソッドは正常に完了しました。 | |
| 入力パラメーターのいずれかの値が無効です。 |
解説(Remarks)
Function Discovery プロバイダー(SSDP および WSD)は、検索パスが完了したことを通知するためにこのメソッドを使用します。
このメソッドからクエリオブジェクトに対して Release を呼び出さないでください。呼び出すとデッドロックが発生する可能性があります。コールバックの処理中に別のスレッドからクエリオブジェクトに対して Release が呼び出された場合、そのオブジェクトはコールバックが完了するまで解放されません。
プロバイダーによって Function Discovery に渡されるすべての通知はキューに格納され、クライアントへ 1 つずつ返されます。コールバックは同期されるため、クライアントが一度に受け取る通知は 1 つだけです。
他の IFunctionDiscoveryNotification メソッドの呼び出しが別のスレッドで行われる可能性があるため、呼び出し中にスレッドの状態に加えた変更は、メソッドを終了する前に元に戻す必要があります。
例
次の例は OnEvent ハンドラーの実装を示しています。CMyNotificationListener クラスは IFunctionDiscoveryNotification のトピックで定義されています。
#include <windows.h>
HRESULT CMyNotificationListener::OnEvent(
IN DWORD dwEventID,
IN FDQUERYCONTEXT fdqcQueryContext,
IN const WCHAR * pszProvider
)
{
HRESULT hr = S_OK;
HANDLE hSearchComplete = INVALID_HANDLE_VALUE;
hSearchComplete = OpenEventW( EVENT_ALL_ACCESS,
FALSE,
L"SearchComplete" );
if( NULL == hSearchComplete )
{
return hr;
}
if( FD_EVENTID_SEARCHCOMPLETE == dwEventID )
{
SetEvent( hSearchComplete );
}
CloseHandle( hSearchComplete );
return hr;
}
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IFunctionDiscoveryNotification "{5F6C1BA8-5330-422E-A368-572B244D3F87}"
#usecom global IFunctionDiscoveryNotification IID_IFunctionDiscoveryNotification "{}"
#comfunc global IFunctionDiscoveryNotification_OnUpdate 3 int,int64,sptr
#comfunc global IFunctionDiscoveryNotification_OnError 4 int,int64,wstr
#comfunc global IFunctionDiscoveryNotification_OnEvent 5 int,int64,wstr
; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。
; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。
; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。