COM の技術概要

このトピックでは、Microsoft コンポーネント オブジェクト モデル (COM) の概要について説明します。

COM の概要

Microsoft コンポーネント オブジェクト モデル (COM) は、実行時に対話する再利用可能なソフトウェア ライブラリを作成するためのバイナリ相互運用性標準を定義します。 COM ライブラリは、アプリケーションにコンパイルする必要なく使用できます。 COM は、Windows メディア プレーヤーや Windows Server など、多くの Microsoft 製品とテクノロジの基盤です。

COM は、多くのオペレーティング システムとハードウェア プラットフォームに適用されるバイナリ標準を定義します。 ネットワーク コンピューティングの場合、COM は、さまざまなハードウェア プラットフォームで実行されるオブジェクト間の相互作用のための標準のワイヤ形式とプロトコルを定義します。 COM は実装言語に依存しないため、C++ や .NET Frameworkのプログラミング言語など、さまざまなプログラミング言語を使用して COM ライブラリを作成できます。

COM 仕様では、クロスプラットフォーム ソフトウェアの再利用を可能にする基本的な概念がすべて提供されています。

  • コンポーネント間の関数呼び出しのバイナリ標準。
  • 厳密に型指定された関数をインターフェイスにグループ化するためのプロビジョニング。
  • ポリモーフィズム、特徴検出、およびオブジェクトの有効期間追跡を提供する基本インターフェイス。
  • コンポーネントとそのインターフェイスを一意に識別するメカニズム。
  • デプロイからコンポーネント インスタンスを作成するコンポーネント ローダー。

COM には、再利用可能なコンポーネントから構築されたアプリケーションの作成を可能にするために連携する多数のパーツがあります。

  • COM 仕様に準拠したランタイム環境を提供する ホスト システム
  • 機能コントラクトを定義するインターフェイスと、インターフェイスを実装するコンポーネント
  • システムにコンポーネントを提供するサーバーと、コンポーネントによって提供される機能を使用するクライアント
  • コンポーネントがローカル ホストとリモート ホストにデプロイされる場所を追跡する レジストリ
  • ローカル ホストとリモート ホスト上のコンポーネントを検索し、サーバーをクライアントに接続する Service Control Manager
  • ホストのファイル システム上のファイルの内容を移動する方法を定義する 構造化ストレージ プロトコル。

ホストとプラットフォーム間でコードを再利用できるようにするのは、COM の中心です。 再利用可能なインターフェイスの実装は、 コンポーネントコンポーネント オブジェクト、または COM オブジェクトという名前です。 コンポーネントは、1 つ以上の COM インターフェイスを実装します。

カスタム COM ライブラリを定義するには、ライブラリが実装するインターフェイスを設計します。 ライブラリのコンシューマーは、ライブラリのデプロイと実装の詳細を知らなくても、その機能を検出して使用できます。

オブジェクトとインターフェイス

COM オブジェクトは、メンバー関数のコレクションである インターフェイスを介してその機能を公開します。 COM インターフェイスは、コンポーネントの期待される動作と責任を定義し、関連する操作の小さなセットを提供する厳密に型指定されたコントラクトを指定します。 COM コンポーネント間のすべての通信はインターフェイスを介して行われ、コンポーネントによって提供されるすべてのサービスはそのインターフェイスを介して公開されます。 呼び出し元は、インターフェイス メンバー関数にのみアクセスできます。 内部状態は、インターフェイスで公開されていない限り、呼び出し元には使用できません。

インターフェイスは厳密に型指定されます。 すべてのインターフェイスには、IID という名前の独自の一意のインターフェイス識別子があり、人間が判読できる名前で発生する可能性のある競合を排除します。 IID はグローバル一意識別子 (GUID) です。これは、Open Software Foundation (OSF) 分散コンピューティング環境 (DCE) によって定義されたユニバーサル一意 ID (UUID) と同じです。 新しいインターフェイスを作成するときは、そのインターフェイスの新しい識別子を作成する必要があります。 呼び出し元がインターフェイスを使用する場合は、一意の識別子を使用する必要があります。 この明示的な識別により、実行時にエラーが発生する名前付けの競合を排除することで、堅牢性が向上します。

新しいインターフェイスを定義する場合は、インターフェイス定義言語 (IDL) を使用してインターフェイス定義を作成できます。 このインターフェイス定義から、Microsoft IDL コンパイラは、インターフェイスを使用するアプリケーションで使用するヘッダー ファイルと、リモート プロシージャ呼び出しを処理するソース コードを生成します。 Microsoft が提供する IDL は、リモート プロシージャ コール (RPC) ベースの分散コンピューティングの業界標準である DCE IDL への単純な拡張機能に基づいています。 IDL はインターフェイス デザイナーの利便性を高めるツールであり、COM 相互運用性の中心ではありません。 IDL では、プログラミング環境ごとにヘッダー ファイルを手動で作成する必要はありません。 詳細については、「 COM インターフェイスの定義」を参照してください。

継承は、COM インターフェイスでは慎重に使用されます。 COM では、基本インターフェイスに関連付けられているコントラクトを再利用する場合にのみ、インターフェイスの継承がサポートされます。 COM では、選択的継承はサポートされていません。したがって、あるインターフェイスが別のインターフェイスから継承する場合は、基本インターフェイスが定義するすべての関数が含まれます。 さらに、インターフェイスでは、複数の継承ではなく単一の継承のみを使用して、基本インターフェイスから関数を取得します。

インターフェイスの実装

COM インターフェイスのインスタンスを単独で作成することはできません。 代わりに、インターフェイスを実装するクラスのインスタンスを作成します。 C++ では、COM インターフェイスは 抽象基本クラスとしてモデル化されます。つまり、インターフェイスは純粋な仮想メンバー関数のみを含む C++ クラスです。 C++ ライブラリは、1 つ以上のインターフェイスからメンバー関数シグネチャを継承し、各メンバー関数をオーバーライドし、各関数の実装を提供することで、COM オブジェクトを実装します。

関数ポインターの概念をサポートする任意のプログラミング言語を使用して、COM インターフェイスを実装できます。 たとえば、C では、インターフェイスは関数ポインターのテーブルへのポインターを含む構造体であり、インターフェイス内のメソッドごとに 1 つずつです。

インターフェイスを実装する場合、クラスはインターフェイス内のすべての関数の実装を提供する必要があります。 クラスにインターフェイス関数で実行する作業がない場合、実装は単一の return ステートメントである可能性があります。

COM クラスは、ファイル システム内の特定のデプロイにクラスを関連付ける一意の 128 ビット クラス ID (CLSID) を使用して識別されます。これは、Windowsが DLL または EXE です。 CLSID は GUID です。これは、同じ CLSID を持つクラスが他にないことを意味します。 一意のクラス識別子を使用すると、クラス間の名前の競合を防ぐことができます。 たとえば、2 つの異なるベンダーが CStack という名前のクラスを記述できますが、両方のクラスに一意の CLSID があるため、競合の可能性は回避されます。

新しい CLSID を取得するには、CoCreateGuid 関数を使用するか、この関数を内部的に呼び出す com オーサリング ツール (Visual Studio など) を使用します。

IUnknown インターフェイス

すべての COM インターフェイスが IUnknown インターフェイスから継承されます。 IUnknown インターフェイスには、ポリモーフィズムとインスタンスの有効期間管理のための基本的な COM 操作が含まれています。 IUnknown インターフェイスには、QueryInterfaceAddRefRelease という名前の 3 つのメンバー関数があります。 IUnknown インターフェイスを実装するには、すべての COM オブジェクトが必要です。

QueryInterface メンバー関数は、COM にポリモーフィズムを提供します。 QueryInterface を呼び出して、COM オブジェクトが特定のインターフェイスをサポートしているかどうかを実行時に判断します。 COM オブジェクトは、要求されたインターフェイスを実装する ppvObject 場合はパラメーター内のインターフェイス ポインターを返し、それ以外の場合は返します NULLQueryInterface メンバー関数を使用すると、COM オブジェクトがサポートするすべてのインターフェイス間のナビゲーションが可能になります。

COM オブジェクト インスタンスの有効期間は、 その参照カウントによって制御されます。 IUnknown メンバー関数 AddRefRelease によってカウントが制御されます。 AddRef によって カウントがインクリメントされ、 リリース によってカウントがデクリメントされます。 参照カウントが 0 に達すると、呼び出し元がインスタンスを使用していないため、 Release メンバー関数によってインスタンスが解放される可能性があります。

クライアント/サーバー モデル

COM クラスは、多数の COM インターフェイスを実装します。 実装は、呼び出し元が COM クラスのインスタンスと対話するときに実行されるバイナリで構成されます。 COM を使用すると、特定のクラスの知識なしで記述されたアプリケーションなど、さまざまなアプリケーションでクラスを使用できます。 Windows プラットフォームでは、動的リンク ライブラリ (DLL) または別のアプリケーション (EXE) にクラスが存在します。

ホスト システムでは、COM は、システムにインストールされている COM オブジェクトのすべての CLSID の登録データベースを保持します。 登録データベースは、各 CLSID と、対応するクラスを格納する DLL または EXE の場所間のマッピングです。 COM は、呼び出し元が COM クラスのインスタンスを作成しようとするたびに、このデータベースに対してクエリを実行します。 呼び出し元は、クラスの新しいインスタンスを要求するために CLSID のみを認識する必要があります。

COM オブジェクトとその呼び出し元の間の相互作用は、クライアントとサーバーの関係としてモデル化されます。 クライアントは、システムから COM オブジェクトを要求する呼び出し元であり、サーバーは、クライアントにサービスを提供する COM オブジェクトを格納するモジュールです。

COM クライアントは、COM オブジェクトのインスタンスを要求するために CLSID をシステムに渡す任意の呼び出し元です。 インスタンスを作成する最も簡単な方法は、COM 関数 CoCreateInstance を呼び出す方法です。

CoCreateInstance 関数は、指定された CLSID の 1 つのインスタンスを作成し、クライアントによって要求された型のインターフェイス ポインターを返します。 クライアントは、インスタンスの使用が完了したときに Release 関数を呼び出して、インスタンスの有効期間を管理する役割を担います。 1 つの CLSID に基づいて複数のオブジェクトを作成するには、 CoGetClassObject 関数を呼び出します。 既に作成されて実行されているオブジェクトに接続するには、 GetActiveObject 関数を呼び出します。

COM サーバーは、システムに COM 実装を提供します。 サーバーは、CLSID を COM クラスに関連付け、クラスの実装を格納し、クラスのインスタンスを作成するためのクラス ファクトリを実装し、サーバーのアンロードを提供します。

注意

COM サーバーは、システムに提供する COM オブジェクトと同じではありません。

 

COM オブジェクトの作成を有効にするには、COM サーバーが IClassFactory インターフェイスの実装を提供する必要があります。 クライアントは CreateInstance メソッドを呼び出して COM オブジェクトの新しいインスタンスを要求できますが、通常、このような要求は CoCreateInstance 関数にカプセル化されます。

COM サーバーは、実行時にクライアントのプロセスに読み込まれる共有ライブラリ (Windows プラットフォーム上の DLL) または実行可能モジュール (Windows プラットフォーム上の EXE) として展開できます。 詳細については、「 COM アプリケーションの登録」を参照してください。

サービス コントロール マネージャー

Service Control Manager (SCM) は、COM オブジェクトのインスタンスに対するクライアント要求を処理します。 次の一覧は、イベントのシーケンスを示しています。

  • クライアントは、COM オブジェクトの CLSID を使用して CoCreateInstance などの関数を呼び出すことによって、COM ライブラリから COM オブジェクトへのインターフェイス ポインターを要求します。
  • COM ライブラリは、SCM に対してクエリを実行して、要求された CLSID に対応するサーバーを検索します。
  • SCM はサーバーを検索し、サーバーによって提供されるクラス ファクトリから COM オブジェクトの作成を要求します。
  • 成功した場合、COM ライブラリはクライアントへのインターフェイス ポインターを返します。

COM システムがサーバー オブジェクトをクライアントに接続すると、クライアントとオブジェクトが直接通信します。 中間ランタイムを介した呼び出しによるオーバーヘッドは追加されません。

COM サーバーをホスト システムに登録するときに、サーバーをアクティブ化するさまざまな方法を指定できます。 次の一覧は、SCM が COM サーバーをアクティブ化する 3 つの方法を示しています。

  • インプロセス: SCM は、オブジェクト サーバーの実装を含む DLL のファイル パスを返します。 COM ライブラリは DLL を読み込み、クラス ファクトリ インターフェイス ポインターを照会します。
  • ローカル: SCM は、起動時にクラス ファクトリを登録するローカル実行可能ファイルを起動し、そのインターフェイス ポインターをシステムとクライアントで使用できます。
  • リモート: ローカル SCM は、リモート コンピューターで実行されている SCM からクラス ファクトリ インターフェイス ポインターを取得します。

クライアントが COM オブジェクトを要求すると、COM ライブラリはローカル ホスト上の SCM にアクセスします。 SCM は、ローカルまたはリモートの可能性がある適切な COM サーバーを見つけ、サーバーはサーバーのクラス ファクトリへのインターフェイス ポインターを返します。 クラス ファクトリが使用可能な場合、COM ライブラリまたはクライアントはクラス ファクトリを使用して、要求されたオブジェクトを作成できます。 詳細については、「 IClassFactory の実装」を参照してください。

再利用性

COM では 、ブラック ボックスの再利用性がサポートされています。つまり、再利用可能なコンポーネントの実装の詳細はクライアントに公開されません。 ブラック ボックスの再利用性を実現するために、COM では、あるオブジェクトが別のオブジェクトを再利用できる 2 つのメカニズムがサポートされています。 再利用の 2 つの形式は、 包含集計という名前です。 慣例により、再利用されるオブジェクトは内部オブジェクトと呼ばれ、 内部オブジェクトを使用するオブジェクトには 外側のオブジェクトという名前が付けられます。

包含では、外側のオブジェクトは内部オブジェクトのクライアントとして動作します。 外側のオブジェクトは内部オブジェクトの論理コンテナーであり、外側のオブジェクトが内部オブジェクトのサービスを使用する場合、外側のオブジェクトは内部オブジェクトのインターフェイスに実装を委任します。 これは、外側のオブジェクトが内部オブジェクトのサービスの観点から実装されることを意味します。 外側のオブジェクトは、内部オブジェクトと同じインターフェイスをサポートしていない場合があり、外側のオブジェクトは、外側のオブジェクトに別のインターフェイスの一部を実装するのに役立つ内部オブジェクトのインターフェイスを使用できます。

集計では、外側のオブジェクトは、外側のオブジェクトに実装されているかのように、内部オブジェクトからインターフェイスを公開します。 これは、外側のオブジェクトがそのインターフェイスの 1 つのすべての呼び出しを常に内部オブジェクトの同じインターフェイスに委任する場合に便利です。 集計は、外側のオブジェクトが追加の実装オーバーヘッドを回避できるようにする便利な機能です。

詳細については、「 オブジェクトの再利用」を参照してください。

Storageオブジェクトとストリーム オブジェクト

COM オブジェクトは、 構造化ストレージを使用してファイルに状態を保存します。これは、ファイル システムセマンティクスを使用してファイルの内容をナビゲーションできるようにする永続的ストレージの一種です。 この方法でファイルの内容を扱うと、増分アクセス、トランザクション、プロセス間の共有などの機能が有効になります。

COM 永続ストレージ仕様では、ストレージ オブジェクトとストリーム オブジェクトの 2 種類のストレージ要素が提供されます。 これらのオブジェクトは COM ライブラリによって実装され、ユーザー アプリケーションがこれらのストレージ要素を実装することはめったにありません。 Storageオブジェクトは IStorage インターフェイスを実装し、ストリーム オブジェクトは IStream インターフェイスを実装します。

ストリーム オブジェクトにはデータが含まれており、概念的にはファイル システム内の 1 つのファイルに似ています。 各ストリームには、アクセス権と 1 つのシーク ポインターがあります。 IStream インターフェイスを使用すると、ストリームの基になるデータに対して、読み取り、書き込み、シーク、その他の操作を実行できます。 ストリームには、テキスト文字列を使用して名前が付けられます。 バイトのフラット ストリームであるため、任意の内部構造を含めることができます。 さらに、 IStream インターフェイスの関数は、ANSI C ランタイム ライブラリの関数など、標準のファイル ハンドル ベースの関数に似ています。

ストレージ オブジェクトは概念的には、ファイル システム内のディレクトリに似ています。 各ストレージには、任意の数のサブオブジェクト オブジェクトと任意の数のストリームを含めることができます。 各ストレージには、独自のアクセス権があります。 IStorage インターフェイスを使用すると、要素の列挙、移動、コピー、名前変更、作成、削除などの操作を実行できます。 ストレージ オブジェクトは、アプリケーション定義データを格納しませんが、格納されている要素 (ストレージとストリーム) の名前を暗黙的に格納します。

Storageオブジェクトとストリーム オブジェクトは、ホスト プラットフォーム上の COM 仕様に従って実装されている場合、プロセス間で共有可能です。 これにより、インプロセスまたはアウトプロセスで実行されているオブジェクトは、ファイル ストレージに対して同じ増分アクセス権を持つことができます。 COM は各プロセスに個別に読み込まれるため、オペレーティング システムでサポートされている共有メモリ メカニズムを使用して、開いている要素の状態とプロセス間のアクセス モードを通信します。

構造化ファイル内のすべてのストレージおよびストリーム オブジェクトには、それを識別するための名前があります。 名前は、特定の規則に従う文字列です。 詳細については、「Storageオブジェクトの名前付け規則」を参照してください。 名前は IStorage 関数に渡され、操作するストレージ内の要素を指定します。 ルート ストレージ オブジェクトの名前は、基になるファイル システムのファイル名と同じであり、これらの名前はファイル システムの規則と制限に従う必要があります。 ファイル名が解釈または変更されずにファイル システムに渡されるストレージ関連の関数に渡される文字列。

ストレージ オブジェクトに含まれる要素の名前は、該当する特定のストレージ オブジェクトの実装によって管理されます。 ストレージ オブジェクトのすべての実装では、長さが 32 文字の要素名をサポートする必要があり、一部の実装では長い名前がサポートされる場合があります。 名前は大文字と小文字を区別せずに保存されますが、大文字と小文字は区別されません。 ストレージ要素名を定義するアプリケーションでは、どちらの状況でも機能する名前を選択する必要があります。

COM によって実装される関数とインターフェイスを使用して、構造化ストレージ ファイル内のすべての要素にアクセスします。 つまり、他のアプリケーションは、ディレクトリのようなサービスを提供する IStorage インターフェイス関数を使用して移動することで、ファイルを参照できます。 また、他のアプリケーションでは、ファイルを書き込んだアプリケーションを実行しなくても、ファイルのデータを使用できます。 COM アプリケーションが別のアプリケーションの構造化ストレージ ファイルにアクセスする場合、標準のWindowsアクセス権が適用され、アプリケーションには十分な特権が必要です。

COM オブジェクトは、永続ストレージに対する読み取りと書き込みを行うことができます。 クライアントは、操作のコンテキストに応じて、COM オブジェクトの永続化関連インターフェイスの 1 つを照会します。 COM オブジェクトは、次のインターフェイスの任意の組み合わせを実装できます。

  • IPersistStorage: COM オブジェクトは、その永続的な状態を読み取り、ストレージ オブジェクトに書き込みます。 クライアントは、このインターフェイスを介して IStorage ポインターをオブジェクトに提供します。 これは、増分アクセスのセマンティクスを含む唯一の永続化インターフェイスです。
  • IPersistStream: COM オブジェクトは、その永続的な状態を読み取り、ストリーム オブジェクトに書き込みます。 クライアントは、このインターフェイスを介して IStream ポインターをオブジェクトに提供します。
  • IPersistFile: COM オブジェクトは、その永続的な状態を、基になるシステム上のファイルに直接読み書きします。 基になるファイルがこれらのインターフェイスを介してアクセスされる場合を除き、このインターフェイスには IStorage または IStream は含まれませんが、 IPersistFile インターフェイスにはストレージとストリームのセマンティクスはありません。 クライアントは、ファイル名をオブジェクトに提供し、 保存 または 読み込み 関数を呼び出します。

データ転送

構造化ストレージは、COM オブジェクトとプロセス間のデータ交換の基礎を提供します。これは、 Uniform Data Transfer という名前です。 OLE 2 で COM が実装される前は、Windows上のデータ転送は、クリップボードやドラッグ ドロップ プロトコルなどの転送プロトコルによって指定されていました。 各転送プロトコルには、プロトコルをクエリにバインドする独自の関数セットがあり、各プロトコルと交換プロシージャを処理するには特定のコードが必要でした。 均一なデータ転送は、IDataObject インターフェイスを使用してすべてのデータ転送を表します。 IDataObject インターフェイスは、一般的なデータ交換操作を転送プロトコルから分離します。

IDataObject インターフェイスは、データ、クエリと列挙、およびオブジェクト内のデータの変更を検出する通知に対する標準の取得および設定操作をカプセル化します。 均一なデータ転送を使用すると、データ形式の豊富な説明と、データ転送に異なるストレージ メディアを使用できます。

均一なデータ転送中に、すべてのプロトコルが IDataObject インターフェイスへのポインターを交換します。 サーバーはデータのソースであり、任意のデータ交換プロトコルで使用できる 1 つのデータ オブジェクトを実装します。 クライアントは、データを使用し、任意のプロトコルから IDataObject ポインターを受け取ったときにデータ オブジェクトからデータを要求します。 ポインター交換が行われた後、両側は IDataObject インターフェイスを介して、均一な方法でデータ交換を処理します。

COM は、均一なデータ転送を可能にする 2 つのデータ構造を定義します。 FORMATETC 構造体は一般化されたクリップボード形式を表し、STGMEDIUM 構造体はメモリ ハンドルとして転送メディアを表します。

クライアントは、データ ソースから要求するデータの種類を示す FORMATETC 構造体を作成し、データ ソースが提供する形式を記述するためにデータ ソースによって使用されます。 クライアントは、 IEnumFORMATETC インターフェイスを要求することで、データ ソースに使用可能な形式を照会します。 詳細については、「 FORMATETC 構造体」を参照してください。

クライアントは STGMEDIUM 構造体を作成して GetData メソッドに渡し、データ オブジェクトは指定 された STGMEDIUM 構造体のデータを返します。

STGMEDIUM 構造体を使用すると、クライアントとデータ ソースの両方で最も効率的な交換メディアを選択できます。 たとえば、交換するデータが非常に大きい場合、データ ソースは、メイン メモリではなく、ディスク ベースのメディアを優先形式として示すことができます。 この柔軟性により、 IStorage または IStream へのポインターを渡すのと同じくらい高速な効率的なデータ交換が可能 になります。 詳細については、 STGMEDIUM 構造体を参照してください。

データ ソースのクライアントでは、データが変更されたときに通知が必要になる場合があります。 COM は、IAdviseSink インターフェイスを実装するアドバイズ シンク オブジェクトを使用して、データ変更通知を処理します。 アドバイズ シンク オブジェクトと IAdviseSink インターフェイスは、 IAdviseSink ポインターをデータ ソースに渡すクライアントによって実装されます。 データ ソースは、基になるデータの変更を検出すると、 IAdviseSink メソッドを呼び出してクライアントに通知します。 詳細については、「 データ通知」を参照してください。

リモート処理

COM を使用すると、リモート計算と分散計算が可能になります。 インターフェイス リモート処理 を使用すると、メンバー関数は、別のプロセスまたは別のホスト コンピューター上にある COM オブジェクトへのインターフェイス ポインターを返します。 インターフェイス リモート処理を実行するインフラストラクチャは、クライアントとオブジェクト サーバーの両方に対して透過的です。 クライアントとサーバーのどちらも、リモート インターフェイスを介して通信するために、相互の展開の詳細を必要としません。 クライアントは、同じインターフェイスでメンバー関数を呼び出して、インプロセスの COM オブジェクト、ローカル ホスト上、またはリモート コンピューター上のプロセス外の COM オブジェクトと通信します。 同じインターフェイスでのローカル呼び出しとリモート呼び出しは、クライアントと区別できません。

COM オブジェクトと通信するために、クライアントは常にインプロセス実装を呼び出します。 COM オブジェクトが処理中の場合、呼び出しは直接です。 COM オブジェクトがアウトプロセスまたはリモートの場合、COM は、リモート プロシージャ コール (RPC) プロトコルを使用してオブジェクトへの呼び出しを転送する プロキシ 実装を提供します。

COM オブジェクトは、インプロセス実装を通じて常にクライアントからの呼び出しを受け取ります。 呼び出し元が処理中の場合、呼び出しは直接です。 呼び出し元がアウトプロセスまたはリモートの場合、COM はクライアント プロセスのプロキシからリモート プロシージャ コールを受信する スタブ 実装を提供します。

マーシャリング は、プロキシからスタブへの転送用に呼び出し履歴をパッケージ化する手順です。 アンマーシャリング は、受信側で発生するアンパックです。 戻り値はマーシャリングされ、スタブからプロキシにマーシャリングされません。 この種の通信は、 ネットワーク経由で通話を送信する場合とも呼ばれます。

各データ型には、マーシャリングの規則があります。 インターフェイス ポインターには、 CoMarshalInterface 関数にカプセル化されたマーシャリング プロトコルもあります。 ほとんどの場合、システムによって提供される 標準インターフェイス マーシャリングで十分ですが、COM オブジェクトは必要に応じて カスタム インターフェイス マーシャリングを 実装して、リモート オブジェクト プロキシの作成を制御できます。 詳細については、「 オブジェクト間通信」を参照してください。

セキュリティ

COM には、2 つの形式のアプリケーション セキュリティが用意されています。 1 つは アクティブ化セキュリティです。このセキュリティでは、新しいオブジェクトの作成方法、クライアントが新規および既存のオブジェクトに接続する方法、クラス テーブルや実行中のオブジェクト テーブルなどの特定のパブリック サービスをセキュリティで保護する方法を指定します。 もう 1 つは、クライアントと COM オブジェクトの間の確立された接続でセキュリティがどのように動作するかを指定する 呼び出しセキュリティです。

アクティブ化セキュリティは、Service Control Manager (SCM) によって自動的に適用されます。 SCM は、COM オブジェクトを取得する要求を受信すると、レジストリに格納されているセキュリティ情報に対して要求をチェックします。

SCM の実装では、通常、デプロイされたクラスを管理したり、ホスト上の特定のユーザー アカウントに対してレジストリ駆動型の構成を提供したりします。 詳細については、「 アクティベーション セキュリティ」を参照してください。

呼び出しセキュリティは自動的に適用されるか、アプリケーションによって適用されます。 アプリケーションがセットアップ情報を提供する場合、COM はアプリケーションをセキュリティで保護するために必要なチェックを実行します。

自動メカニズムは、プロセスのセキュリティをチェックしますが、個々のオブジェクトやメソッドについてはチェックしません。 アプリケーションでさらにきめ細かなセキュリティが必要な場合、COM は、アプリケーションが独自のセキュリティ チェックを実行するために使用できる関数を提供します。

自動メカニズムとカスタム メカニズムを組み合わせて使用できるため、アプリケーションは COM に自動セキュリティ チェックを実行し、独自のセキュリティ チェックを実行するように求める場合があります。

COM 呼び出しセキュリティ サービスは、次のカテゴリに分かれています。

  • クライアントとサーバーの両方によって呼び出される一般的な関数。自動セキュリティ メカニズムを初期化し、自動認証サービスを登録できるようにします。 一般的な呼び出しセキュリティ API は 、CoInitializeSecurity 関数と CoQueryAuthenticationServices 関数です
  • クライアント プロキシ上のインターフェイス。クライアントは、個々のインターフェイスへの呼び出しのセキュリティを制御できます。 IClientSecurity インターフェイスと CoQueryProxyBlanketCoSetProxyBlanketおよび CoCopyProxy 関数は、リモート オブジェクトの呼び出しセキュリティを提供します。
  • サーバー側関数と呼び出しコンテキスト インターフェイス。このインターフェイスを使用すると、サーバーは呼び出しに関するセキュリティ情報を取得し、呼び出し元を偽装できます。 IServerSecurity インターフェイスと CoGetCallContextCoImpersonateClientおよび CoRevertToSelf 関数は、サーバー側の呼び出しセキュリティを提供します。

多くの場合、クライアントは COM オブジェクトに対して IClientSecurity インターフェイスを照会します。このインターフェイスはリモート処理レイヤーによってローカルに実装されます。 クライアントは、このインターフェイスを使用して、いずれかのインターフェイスで呼び出しを行う前に、COM オブジェクト上の個々のインターフェイス プロキシのセキュリティを制御します。

呼び出しがサーバーに到着すると、サーバーは CoGetCallContext 関数を呼び出して IServerSecurity インターフェイスを取得できます。これにより、サーバーはクライアントの認証を確認し、必要に応じてクライアントを偽装できます。 IServerSecurity オブジェクトは、呼び出しの間有効です。

CoInitializeSecurity 関数を呼び出してセキュリティ レイヤーを初期化し、指定した値をセキュリティの既定値として設定します。 プロセスが CoInitializeSecurity を呼び出さない場合、COM はインターフェイスが初めてマーシャリングまたはマーシャリング解除されるときに自動的に呼び出し、システムの既定のセキュリティを登録します。 CoInitializeSecurity 関数を使用すると、クライアントはプロセスの既定の呼び出しセキュリティを確立できるため、個々のプロキシで IClientSecurity を使用する必要がなくなります。 CoInitializeSecurity 関数を使用すると、サーバーはプロセスの自動認証サービスを登録できます。 詳細については、「 CoInitializeSecurity を使用したセキュリティProcess-Wide設定」を参照してください。

COM クライアントとサーバー

COM インターフェイスの定義

COM アプリケーションの登録

COM のセキュリティ

プロセス、スレッド、およびアパートメント