IExternalConnection
COM公式ドキュメント
IExternalConnection (objidlbase.h) インターフェイスは、サーバーオブジェクトのマーシャリングされた接続 (外部接続) の数を管理します。
解説(Remarks)
IExternalConnection は、埋め込みオブジェクトへのリンクをサイレント更新後に整然とシャットダウンできるようにするため、通常はサーバーオブジェクトに実装されます。IExternalConnection を実装しないオブジェクトは、このような状況でデータを失うおそれがあります。最後のリンククライアントが埋め込み (サーバー) オブジェクトを解放すると、そのオブジェクトのスタブマネージャー上の最後の外部接続が解放されます。これにより、スタブマネージャーは埋め込みオブジェクト上のインターフェイスへのポインターを解放し、オブジェクトのシャットダウンを開始します。この時点でサーバーオブジェクトはリンクコンテナーに対して IOleClientSite::SaveObject を呼び出しますが、スタブマネージャーはもはや埋め込みオブジェクトへのポインターを持っていないため、リンクコンテナーからの IPersistStorage::Save への戻り呼び出しは失敗します。その結果、サーバーオブジェクトのデータに対する未保存の変更は失われます。
しかし、サーバーオブジェクトが IExternalConnection を実装している場合、最後の外部接続が解放されても、そのスタブマネージャーはオブジェクトへの接続を解放しません。代わりに、オブジェクトが自身を破棄する準備が整うまで接続を維持します。
標準マーシャリングでは、オブジェクトの外部接続数をインクリメントするため、オブジェクトが最初にマーシャリングされたときに COM がそのオブジェクトに対して IExternalConnection::AddConnection を呼び出します。以降の外部接続が取得および解放されると、スタブマネージャーはオブジェクトに対して IExternalConnection のメソッドを呼び出します。オブジェクトの外部接続数がゼロになると、オブジェクトはデータを保存し、実行中オブジェクトテーブルから自身を登録解除し、オブジェクト参照カウントをゼロにするために必要なその他の処理を行うことができます。
IExternalConnection を実装するオブジェクトは、外部参照カウントが 0 に達したとき、自身に対して明示的に CoDisconnectObject を呼び出す必要があります。この呼び出しにより、スタブマネージャーはオブジェクトに対して Release を呼び出し、オブジェクトが自身を破棄できるようにします。
メソッド 2
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
IExternalConnection::AddConnection (objidlbase.h) メソッドは、オブジェクトの強い外部接続の数をインクリメントします。
| extconn | DWORD | in | オブジェクトへの外部接続の種類。このインターフェイスで現在サポートされている外部接続の種類は強い接続 (strong) のみであり、これはこの外部接続が存在する限りオブジェクトが生存し続けなければならないことを意味します。強い外部接続は値 EXTCONN_STRONG で表され、これは列挙型 EXTCONN で定義されています。 |
| reserved | DWORD | in | 接続に関する情報。このパラメーターは OLE による使用のために予約されています。その値はゼロの場合もありますが、必ずしもそうとは限りません。したがって、AddConnection の実装には、ゼロの値が返されるかどうかに実行が依存するようなコードブロックを含めるべきではありません。 |
戻り値
このメソッドは接続数を返します。この値はデバッグ目的のみに使用することを意図しています。
解説(Remarks)
EXE オブジェクトサーバーによって作成されたオブジェクトは、リンククライアントがアクティブ化され、それによってオブジェクトに外部ロックが作成されるたびに、AddConnection を呼び出すためにスタブマネージャーに依存します。リンククライアントが接続を切断すると、スタブマネージャーはロックを解放するために IExternalConnection::ReleaseConnection を呼び出します。
DLL オブジェクトアプリケーションはそのオブジェクトと同じプロセス空間に存在するため、RPC (リモートプロシージャコール) を使用せず、外部接続を追跡するスタブマネージャーも持ちません。したがって、オブジェクトへの外部リンクをサポートする DLL サーバーは、接続が追加または解放されたときにリンククライアントがインターフェイスを直接呼び出して通知できるように、IExternalConnection を実装する必要があります。
以下は AddConnection メソッドの一般的な実装です。
DWORD MyInterface::AddConnection(DWORD extconn, DWORD dwReserved)
{
return extconn & EXTCONN_STRONG ? ++m_cStrong : 0;
}
IExternalConnection::ReleaseConnection (objidlbase.h) メソッドは、オブジェクトの強い外部接続の数をデクリメントします。
| extconn | DWORD | in | オブジェクトへの外部接続の種類。このインターフェイスで現在サポートされている外部接続の種類は強い接続 (strong) のみであり、これはこの外部接続が存在する限りオブジェクトが生存し続けなければならないことを意味します。強い外部接続は値 EXTCONN_STRONG で表され、これは列挙型 EXTCONN で定義されています。 |
| reserved | DWORD | in | 接続に関する情報。このパラメーターは OLE による使用のために予約されています。その値はゼロの場合もありますが、必ずしもそうとは限りません。したがって、ReleaseConnection の実装には、ゼロの値が返されるかどうかに実行が依存するようなコードブロックを含めるべきではありません。 |
| fLastReleaseCloses | BOOL | in | 解放される接続がオブジェクト上の最後の外部ロックであり、そのためオブジェクトを閉じるべき場合、このパラメーターは TRUE になります。それ以外の場合、オブジェクトはユーザーまたは別のプロセスによって閉じられるまで開いたままにしておく必要があります。 |
戻り値
このメソッドは接続数を返します。この値はデバッグ目的のみに使用することを意図しています。
解説(Remarks)
fLastReleaseCloses が TRUE の場合、ReleaseConnection を呼び出すとオブジェクトは自身をシャットダウンします。このメソッドの呼び出しは、コンテナーアプリケーションと同じプロセス空間で実行される DLL オブジェクトが、サイレント更新後にいつ閉じるべきかを知る唯一の方法です。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IExternalConnection "{00000019-0000-0000-C000-000000000046}"
#usecom global IExternalConnection IID_IExternalConnection "{}"
#comfunc global IExternalConnection_AddConnection 3 int,int
#comfunc global IExternalConnection_ReleaseConnection 4 int,int,int
; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。
; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。