COM の技術概要
このトピックでは、Microsoft Component Object Model (COM) の概要について説明します:
- COM の概要
- オブジェクトとインターフェイス
- インターフェイスの実装
- IUnknownインターフェイス
- クライアント/サーバー モデル
- サービス コントロール マネージャー
- 再利用性
- ストレージとストリーム オブジェクト
- データ転送
- リモート処理
- セキュリティ
- 関連トピック
COM の概要
Microsoft Component Object Model (COM) は、実行時に対話する再利用可能なソフトウェア ライブラリを作成するためのバイナリ相互運用性標準を定義します。 COM ライブラリは、アプリケーションにコンパイルしなくても使用できます。 COM は、Windows Media Player や Windows Server など、多数のマイクロソフト製品およびテクノロジの基盤です。
COM は、多くのオペレーティングシステムおよびハードウェアプラットフォームに適用されるバイナリ標準を定義します。 ネットワーク コンピューティングの場合、COM は、さまざまなハードウェア プラットフォームで実行されるオブジェクト間の相互作用のための標準ワイヤ形式とプロトコルを定義します。 COM は実装言語に依存しません。つまり、C++ や NET Framework の言語など、さまざまなプログラミング言語を使用して COM ライブラリを作成できます。
COM 仕様は、クロスプラットフォームソフトウェアの再利用を可能にする基本的な概念をすべて提供します:
- コンポーネント間の関数呼び出しのバイナリ標準。
- 厳密に型指定された関数をインターフェイスにグループ化するための規定。
- ポリモーフィズム、機能検出、およびオブジェクトの有効期間の追跡を提供する基本インターフェイス。
- コンポーネントとそのインターフェイスを一意に識別するメカニズム。
- デプロイからコンポーネントインスタンスを作成するコンポーネントローダー。
COMには、再利用可能なコンポーネントから構築されたアプリケーションの作成を可能にするために連携する多数の部分があります。
- COM仕様に準拠したランタイム環境を提供するホストシステム。
- 機能契約を定義するインターフェイスと、インターフェイスを実装するコンポーネント。
- システムにコンポーネントを提供するサーバーと、コンポーネントが提供する機能を使用するクライアント。
- ローカルおよびリモートホストでコンポーネントがデプロイされている場所を追跡するレジストリ。
- ローカルおよびリモートホスト上のコンポーネントを検索し、サーバーをクライアントに接続するサービスコントロールマネージャー。
- ホストのファイルシステム上のファイルの内容をナビゲートする方法を定義する構造化ストレージプロトコル。
ホストとプラットフォーム間でコードを再利用できるようにすることは、COMの中心です。 再利用可能なインターフェイス実装は、コンポーネント、コンポーネントオブジェクト、またはCOMオブジェクトと呼ばれます。 コンポーネントは、1つ以上のCOMインターフェイスを実装します。
カスタムCOMライブラリを定義するには、ライブラリが実装するインターフェイスを設計します。 ライブラリのコンシューマーは、ライブラリの展開と実装の詳細を知らなくても、その機能を検出して使用できます。
オブジェクトとインターフェイス
COMオブジェクトは、メンバー関数の集合であるインターフェイスを通じてその機能を公開します。 COMインターフェイスは、コンポーネントの予期される動作と責任を定義し、関連する操作の小さなセットを提供する厳密に型指定されたコントラクトを指定します。 COMコンポーネント間のすべての通信はインターフェイスを介して行われ、コンポーネントによって提供されるすべてのサービスはそのインターフェイスを介して公開されます。 呼び出し元は、インターフェイスメンバー関数にのみアクセスできます。 内部状態は、インターフェイスで公開されていない限り、呼び出し元では使用できません。
インターフェイスは厳密に型指定されます。 すべてのインターフェイスには、IIDという名前の一意のインターフェイス識別子があります。これにより、人間が判読できる名前で発生する可能性がある競合が排除されます。 IIDはグローバル一意識別子 (GUID) であり、Open Software Foundation (OSF) Distributed Computing Environment (DCE) によって定義されたユニバーサル一意識別子 (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クラスは、クラスをファイルシステム内の特定の展開 (Windowsの場合はDLLまたはEXE) に関連付ける一意の128ビットクラスID (CLSID) を使用して識別されます。 CLSIDはGUIDであり、他のクラスに同じCLSIDがないことを意味します。 一意のクラス識別子を使用すると、クラス間の名前の競合を防ぐことができます。 たとえば、2つの異なるベンダーがCStackという名前のクラスを記述できますが、両方のクラスに一意のCLSIDがあるため、競合の可能性は回避されます。
新しい CLSID を取得するには、CoCreateGuid 関数を使用するか、この関数を内部で呼び出す COM オーサリング ツール (Visual Studioなど) を使用します。
IUnknown インターフェイス
すべての COM インターフェイスは IUnknown インターフェイスから継承されます。 IUnknown インターフェイスには、ポリモーフィズムとインスタンスのライフタイム管理のための基本的なCOM操作が含まれています。 IUnknown インターフェイスには、QueryInterface、AddRef、Release という名前の3つのメンバー関数があります。 すべての COM オブジェクトは IUnknown インターフェイスを実装する必要があります。
QueryInterface メンバー関数は COM のポリモーフィズムを提供します。 COM オブジェクトが特定のインターフェイスをサポートしているかどうかを実行時に判断するには、QueryInterface を呼び出します。 COM オブジェクトは、要求されたインターフェイスを実装している場合、ppvObject
パラメーターでインターフェイスポインターを返し、そうでない場合はNULL
を返します。 QueryInterface メンバー関数により、COM オブジェクトがサポートするすべてのインターフェイス間でのナビゲーションが可能になります。
COM オブジェクトインスタンスのライフタイムは、その参照カウントによって制御されます。 IUnknown メンバー関数と AddRefおよびRelease がカウントを制御します。 AddRef はカウントを増やし、Release はカウントを減らします。 参照カウントがゼロになると、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 関数を呼び出して、インスタンスのライフタイムを管理する責任があります。 単一のCLSIDに基づいて複数のオブジェクトを作成するには、CoGetClassObject 関数を呼び出します。 すでに作成され、実行中のオブジェクトに接続するには、GetActiveObject 関数を呼び出します。
COM サーバーは、システムに COM 実装を提供します。 サーバーは、CLSID を COM クラスに関連付け、クラスの実装を格納し、クラスのインスタンスを作成するためのクラス ファクトリを実装し、サーバーをアンロードするために提供します。
メモ
COM サーバーは、システムに提供する COM オブジェクトと同じではありません。
COMオブジェクトを作成するために、COMサーバーはIClassFactoryインターフェイスの実装を提供する必要があります。 クライアントはCreateInstanceメソッドを呼び出してCOMオブジェクトの新しいインスタンスを要求できますが、通常、そのような要求はCoCreateInstance関数内にカプセル化されます。
COMサーバーは、実行時にクライアントのプロセスに読み込まれる共有ライブラリ (WindowsプラットフォームのDLL) または実行可能モジュール (WindowsプラットフォームのEXE) として展開できます。 詳細については、「COMアプリケーションの登録」を参照してください。
サービスコントロールマネージャー
サービスコントロールマネージャー (SCM) は、COMオブジェクトのインスタンスに対するクライアント要求を処理します。 次の一覧は、イベントのシーケンスを示しています。
- クライアントは、COMオブジェクトのCLSIDを指定してCoCreateInstanceなどの関数を呼び出して、COMライブラリからCOMオブジェクトへのインターフェイスポインターを要求します。
- COMライブラリは、要求されたCLSIDに対応するサーバーを検索するためにSCMにクエリを実行します。
- 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つの形態はコンテインメントとアグリゲーションと呼ばれます。 慣習的に、再利用されるオブジェクトは内部オブジェクトと呼ばれ、内部オブジェクトを使用するオブジェクトは外部オブジェクトと呼ばれます。
コンテインメントでは、外部オブジェクトは内部オブジェクトのクライアントとして動作します。 外部オブジェクトは内部オブジェクトの論理コンテナーであり、外部オブジェクトが内部オブジェクトのサービスを使用する場合、外部オブジェクトは実装を内部オブジェクトのインターフェイスに委任します。 これは、外部オブジェクトが内部オブジェクトのサービスの観点から実装されることを意味します。 外部オブジェクトは、内部オブジェクトと同じインターフェイスをサポートしていない場合があり、外部オブジェクトは内部オブジェクトのインターフェイスを使用して、外部オブジェクトに異なるインターフェイスの一部を実装することができます。
アグリゲーションでは、外部オブジェクトは、外部オブジェクトに実装されているかのように、内部オブジェクトからインターフェイスを公開します。 これは、外部オブジェクトが、そのインターフェイスのいずれかでのすべての呼び出しを常に内部オブジェクトの同じインターフェイスに委任する場合に便利です。 アグリゲーションは、外部オブジェクトが追加の実装オーバーヘッドを回避できるようにする便利な機能です。
詳細については、「オブジェクトの再利用」を参照してください。
ストレージとストリームオブジェクト
COMオブジェクトは、構造化ストレージを使用して状態をファイルに保存します。構造化ストレージは、ファイルシステムセマンティクスを使用してファイルの内容のナビゲーションを可能にする永続ストレージの形式です。 この方法でファイルの内容を処理すると、増分アクセス、トランザクション、プロセス間の共有などの機能が有効になります。
COM永続ストレージ仕様には、ストレージオブジェクトとストリームオブジェクトの2種類のストレージ要素が用意されています。 これらのオブジェクトはCOMライブラリによって実装され、ユーザーアプリケーションがこれらのストレージ要素を実装することはほとんどありません。 ストレージオブジェクトはIStorageインターフェイスを、ストリームオブジェクトはIStreamインターフェイスを実装します。
ストリームオブジェクトにはデータが含まれており、概念的にはファイルシステム内の単一のファイルに似ています。 各ストリームには、アクセス権と単一のシークポインターがあります。 IStreamインターフェイスを通じて、ストリームの基礎となるデータに対して読み取り、書き込み、シーク、その他の操作を行うことができます。 ストリームには、テキスト文字列を使用して名前が付けられます。 これはバイトのフラットストリームであるため、任意の内部構造を含めることができます。 さらに、IStreamインターフェイスの関数は、ANSI Cランタイムライブラリの標準的なファイルハンドルベースの関数と似ています。
ストレージオブジェクトは、概念的にはファイルシステムのディレクトリに似ています。 各ストレージには、任意の数のサブストレージオブジェクトと任意の数のストリームを含めることができます。 各ストレージには独自のアクセス権があります。 IStorageインターフェイスを通じて、列挙、移動、コピー、名前変更、作成、要素の削除などの操作を行うことができます。 ストレージオブジェクトは、アプリケーション定義のデータを格納しませんが、含まれている要素 (ストレージとストリーム) の名前を暗黙的に格納します。
ストレージオブジェクトとストリームオブジェクトは、ホストプラットフォームのCOM仕様に従って実装されている場合、プロセス間で共有できます。 これにより、インプロセスまたはアウトプロセスで実行されているオブジェクトは、ファイルストレージに対して同じ増分アクセスを行うことができます。 COMは各プロセスに個別に読み込まれるため、オペレーティングシステムでサポートされている共有メモリメカニズムを使用して、開いている要素の状態とそのアクセスモードをプロセス間で通信します。
構造化ファイル内のすべてのストレージおよびストリームオブジェクトには、識別するための名前があります。 名前は、特定の規則に従った文字列です。 詳細については、「ストレージオブジェクトの命名規則」を参照してください。 名前は、ストレージ内の操作対象の要素を指定するためにIStorage関数に渡されます。 ルートストレージオブジェクトの名前は、基になるファイルシステムのファイル名と同じであり、これらの名前はファイルシステムの規則と制限に従う必要があります。 名前ファイルが解釈または変更されずにファイルシステムに渡されるストレージ関連の関数に渡される文字列。
ストレージオブジェクト内に含まれる要素の名前は、対象となる特定のストレージオブジェクトの実装によって管理されます。 ストレージオブジェクトのすべての実装では、32文字の長さの要素名をサポートする必要があり、一部の実装ではより長い名前をサポートする場合があります。 名前は大文字と小文字を区別して保存されますが、大文字と小文字は区別されません。 ストレージ要素名を定義するアプリケーションでは、どちらの状況でも機能する名前を選択する必要があります。
構造化ストレージファイル内のすべての要素にアクセスするには、COMによって実装される関数とインターフェイスを使用します。 これは、他のアプリケーションが、ディレクトリのようなサービスを提供するIStorageインターフェイス関数を使ってファイルをナビゲートすることでファイルを閲覧できることを意味します。 また、他のアプリケーションは、ファイルを記述したアプリケーションを実行しなくても、ファイルのデータを使用できます。 COMアプリケーションが別のアプリケーションの構造化ストレージファイルにアクセスするときは、標準のWindowsアクセス権が適用され、アプリケーションに十分な特権が必要です。
COMオブジェクトは、それ自体を永続ストレージに対して読み書きできます。 クライアントは、操作のコンテキストに応じて、COMオブジェクトの永続化に関連するインターフェイスのいずれかを照会します。 COMオブジェクトは、次のインターフェイスの任意の組み合わせを実装できます。
- IPersistStorage: COMオブジェクトは、ストレージオブジェクトに対してその永続的な状態を読み書きします。 クライアントは、このインターフェイスを通じてオブジェクトにIStorageポインターを提供します。 これは、増分アクセスのセマンティクスを含む唯一の永続化インターフェイスです。
- IPersistStream: COMオブジェクトは、その永続的な状態をストリームオブジェクトに読み書きします。 クライアントは、このインターフェイスを通じてオブジェクトにIStreamポインターを提供します。
- IPersistFile: COMオブジェクトは、その永続的な状態を直接、基礎となるシステムのファイルに読み書きします。 このインターフェイスは、基礎となるファイルがこれらのインターフェイスを通じてアクセスされる場合を除き、IStorageまたはIStreamを含まないが、IPersistFileインターフェイスはストレージとストリームに対する構文を持っていません。 クライアントは、オブジェクトにファイル名を提供し、SaveまたはLoad関数を呼び出します。
データ転送
構造化ストレージは、COMオブジェクトとプロセス間のデータ交換の基礎を提供し、これは一様なデータ転送と呼ばれます。 OLE 2でCOMが実装される前、Windows上のデータ転送は、クリップボードやドラッグアンドドロッププロトコルなどの転送プロトコルによって指定されていました。 各転送プロトコルには、プロトコルをクエリにバインドする独自の関数セットがあり、それぞれのプロトコルと交換手順を処理するために特定のコードが必要でした。 一様なデータ転送は、転送プロトコルから一般的なデータ交換操作を分離する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はリモートプロシージャコール(RPC)プロトコルを使用してオブジェクトに呼び出しを転送するプロキシ実装を提供します。
COMオブジェクトは、常にインプロセス実装を通じてクライアントから呼び出しを受信します。 呼び出し元がインプロセスの場合、呼び出しは直接です。 呼び出し元がプロセス外またはリモートの場合、COMはクライアントプロセスのプロキシからリモートプロシージャ呼び出しを受信するスタブ実装を提供します。
マーシャリングは、プロキシからスタブへの転送のための呼び出しスタックのパッケージング手順です。 マーシャリング解除は、受信側で発生するパッケージ解除です。 戻り値は、スタブからプロキシにマーシャリングおよびマーシャリング解除されます。 This kind of communication is also referred to as sending a callネットワーク経由の呼び出し送信とも言われます。
各データ型には、マーシャリングの規則があります。 インターフェイスポインターにもマーシャリングプロトコルがあり、それはCoMarshalInterface関数にカプセル化されています。 ほとんどの場合、システムによって提供される標準インターフェイスマーシャリングが十分ですが、COMオブジェクトはオプションでカスタムインターフェイスマーシャリングを実装して、自身へのリモートオブジェクトプロキシの作成を制御することができます。 詳細については、「オブジェクト間通信」を参照してください。
セキュリティ
COMには、2つの形式のアプリケーションセキュリティが用意されています。 1つはアクティベーションセキュリティ、新しいオブジェクトの作成方法、クライアントが新規および既存のオブジェクトに接続する方法、およびクラステーブルや実行オブジェクトテーブルなどの特定の公開サービスがどのように保護されるかを指定します。 もう1つは呼び出しセキュリティ、クライアントとCOMオブジェクト間の確立された接続でセキュリティがどのように動作するかを指定します。
アクティベーションセキュリティは、サービスコントロールマネージャー (SCM) によって自動的に適用されます。 SCMは、COMオブジェクトを取得する要求を受信すると、レジストリに格納されているセキュリティ情報に対して要求を確認します。
SCMの実装では、通常、展開されたクラスとホスト上の特定のユーザーアカウントを管理するためのレジストリドリブン構成が提供されます。 詳細については、「アクティベーションセキュリティ」を参照してください。
呼び出しセキュリティは、自動的に適用されるか、アプリケーションによって適用されます。 アプリケーションがセットアップ情報を提供する場合、COMはアプリケーションをセキュリティで保護するために必要なチェックを実行します。
自動メカニズムは、プロセスのセキュリティをチェックしますが、個々のオブジェクトやメソッドのセキュリティはチェックしません。 アプリケーションがより詳細なセキュリティを必要とする場合、COMには、アプリケーションが独自のセキュリティチェックを実行するために使用できる関数が用意されています。
自動メカニズムとカスタムメカニズムは一緒に使用できるため、アプリケーションはCOMに自動セキュリティチェックを実行するように要求してから、独自のセキュリティチェックを実行することができます。
COM呼び出しセキュリティサービスは、次のカテゴリに分類されます。
- クライアントとサーバーの両方から呼び出される一般的な関数。これにより、自動セキュリティメカニズムを初期化し、自動認証サービスを登録できます。 一般的な呼び出しセキュリティ API は、CoInitializeSecurity 関数と CoQueryAuthenticationServices 関数です。
- クライアント プロキシ上のインターフェイス。これにより、クライアントは個々のインターフェイスの呼び出しのセキュリティを制御できます。 IClientSecurityインターフェイスとCoQueryProxyBlanket、CoSetProxyBlanket、CoCopyProxy関数は、リモートオブジェクトの呼び出しセキュリティを提供します。
- サーバー側関数と呼び出しコンテキストインターフェイス。これにより、サーバーは呼び出しに関するセキュリティ情報を取得し、呼び出し元を偽装することができます。 IServerSecurityインターフェイスとCoGetCallContext、CoImpersonateClient、CoRevertToSelf関数は、サーバー側の呼び出しセキュリティを提供します。
クライアントは通常、リモート処理レイヤーによってローカルで実装されるIClientSecurityインターフェイスをCOMオブジェクトに問い合わせます。 クライアントは、このインターフェイスを使用して、いずれかのインターフェイスで呼び出しを行う前に、COMオブジェクト上の個々のインターフェイスプロキシのセキュリティを制御します。
呼び出しがサーバーに到着すると、サーバーは必要に応じてCoGetCallContext関数を呼び出してIServerSecurityインターフェイスを取得し、クライアントの認証を確認し、必要に応じてクライアントを偽装します。 IServerSecurityオブジェクトは、呼び出しの期間中有効です。
CoInitializeSecurity関数を呼び出してセキュリティレイヤーを初期化し、指定された値をセキュリティのデフォルトとして設定します。 プロセスがCoInitializeSecurityを呼び出さない場合、COMはインターフェイスが最初にマーシャリングまたはマーシャリング解除されたときに自動的に呼び出し、システムのデフォルトセキュリティを登録します。 CoInitializeSecurity関数により、クライアントはプロセスのデフォルトの呼び出しセキュリティを確立でき、これにより個々のプロキシでIClientSecurityの使用を避けることができます。 CoInitializeSecurity関数により、サーバーはプロセスの自動認証サービスを登録できます。 詳細については、「CoInitializeSecurityを使用したプロセス全体のセキュリティ設定」を参照してください。
関連トピック