次の方法で共有


インターフェイスとメソッドの設計をより良いものにする IDL 手法

準拠データとバリアント データの両方を処理する RPC インターフェイスとメソッドを開発する場合は、次の IDL 固有の手法を使用してセキュリティとパフォーマンスを向上することを検討してください。 このトピックで参照される属性は、準拠データ ([size_is] 属性や [max_is] 属性など) またはバリアント データ ([length_is] 属性や [string] 属性など) を処理するメソッド パラメーターに設定される IDL 属性です。

[range] 属性と準拠データ パラメーターの使用

[range] 属性は、データのマーシャリング解除プロセス中に追加のサイズ検証を実行するよう RPC ランタイムに指示します。 具体的には、関連付けられたパラメーターとして渡されるデータの指定されたサイズが指定された範囲内にあることを確認します。

[range] 属性はワイヤ形式には影響しません。

ネットワーク上の値が許容範囲外の場合、RPC は RPC_X_INVALID_BOUND 例外または RPC_X_BAD_STUB_DATA 例外をスローします。 これにより、追加のレベルのデータ検証が提供され、バッファー オーバーランなどの一般的なセキュリティ エラーを防ぐことができます。 同様に、[range] を使用すると、マークされた準拠データに RPC サービスで考慮できる制約が明確に定義されるため、アプリケーションのパフォーマンスを向上させることができます。

RPC サーバー スタブ メモリ管理規則

RPC 対応アプリケーションの IDL ファイルを作成する場合は、RPC サーバー スタブ メモリ管理規則を理解することが重要です。 アプリケーションは、[range] を上記の準拠データと組み合わせて使用し、[length_is] のような可変長データ IDL 属性を意図的に適用しないようにすることで、サーバー リソースの使用率を向上させることができます。

IDL ファイルで定義されているデータ構造フィールドに [length_is] を適用することは推奨されません。

可変長データ パラメーターの推奨される手順

可変サイズのデータ構造、メソッド パラメーター、およびフィールドの IDL 属性を定義する場合に考慮すべき推奨される手順をいくつか次に示します。

  • 早期相関を使用する。 一般に、可変サイズのパラメーターまたはフィールドは、制御する整数型の直後に発生するように定義することをお勧めします。

    たとえば、 にします。

    earlyCorr
    (
    [in, range(MIN_COUNT, MAX_COUNT)] long size, 
    [in,size_is(size)] char *pv
    );
    

    この形式が次の形式より推奨されます。

    lateCorr
    (
    [in,size_is(size)] char *pv, 
    [in, range(MIN_COUNT, MAX_COUNT)] long size)
    );
    

    ここで、earlyCorr は可変長データ パラメーターの直前にサイズ パラメーターを宣言し、lateCorr ではその後にサイズ パラメーターを宣言します。 早期対応を使用すると、特にメソッドが頻繁に呼び出される場合に、全体的なパフォーマンスが向上します。

  • [out, size_is] 属性タプルでマークされたパラメーターで、クライアント側でデータ長が既知であるかクライアントに合理的な上限がある場合、メソッド定義はパラメーターの属性とシーケンスの点で次のように類似している必要があります。

    outKnownSize
    (
    [in,range(MIN_COUNT, MAX_COUNT)] long lSize,
    [out,size_is(lSize)] UserDataType * pArr
    );
    

    この場合、クライアントは pArr に対して固定サイズ バッファーを提供するため、サーバー側の RPC サービスは適度に保証された適切なサイズのバッファーを割り当てることができます。 この例では、データはサーバー ([out]) から受信されることに注意してください。 定義は、サーバー ([in]) に渡されるデータに類似しています。

  • RPC アプリケーションのサーバー側コンポーネントがデータ長を決定する場合、メソッド定義は次のように類似している必要があります。

    typedef [range(MIN_COUNT,MAX_COUNT)] long RANGED_LONG;
    
    outUnknownSize
    (
    [out] RANGED_LONG *pSize,
    [out,size_is(,*pSize)] UserDataType **ppArr
    );
    

    RANGED_LONG は、クライアント スタブとサーバー スタブの両方に対して定義され、クライアントが正しく予測できる指定されたサイズの型です。 この例では、クライアントは ppArrNULL として渡し、RPC サーバー アプリケーション コンポーネントは正しいメモリ量を割り当てます。 返されると、クライアント側の RPC サービスは、返されたデータのメモリを割り当てます。

  • クライアントが大きな準拠配列のサブセットをサーバーに送信する場合、アプリケーションは次の例に示すようにサブセットのサイズを指定できます。

    inConformantVaryingArray
    (
    [in,range(MIN_COUNT,MAX_COUNT)] long lSize,
    [in] long lLength, 
    [in,size_is(lSize), length_is(lLength)] UserDataType *pArr
    );
    

    これにより、RPC は配列の lLength 要素のみをネットワーク経由で送信します。 ただし、この定義により、RPC サービスはサイズ lSize のメモリをサーバー側に強制的に割り当てます。

  • クライアント アプリケーション コンポーネントが、サーバーが返せる配列の最大サイズを決定するものの、サーバーがその配列のサブセットを送信できるようにする場合、アプリケーションは次の例のように IDL を定義することで、このような動作を指定できます。

    inMaxSizeOutLength
    (
    [in, range(MIN_COUNT, MAX_COUNT)] long lSize,
    [out] long *pLength,
    [out,size_is(lSize), length_is(*pLength)] UserDataType *pArr
    );
    

    クライアント アプリケーション コンポーネントは配列の最大サイズを指定し、サーバーはクライアントに送り返す要素の数を指定します。

  • サーバー アプリケーション コンポーネントがクライアント アプリケーション コンポーネントに文字列を返す必要があり、クライアントがサーバーから返される最大サイズを把握している場合、アプリケーションは次の例に示すように、準拠する文字列型を使用できます。

    outStringKnownSize
    (
    [in,range(MIN_COUNT, MAX_STRING)] long lSize,
    [out,size_is(lSize),string] wchar_t *pString
    );
    
  • クライアント アプリケーション コンポーネントが文字列のサイズを制御しない場合、RPC サービスは、次の例に示すようにメモリを特別に割り当てることができます。

    outStringUnknownSize
    (
    [out] LPWSTR *ppStr
    );
    

    クライアント アプリケーション コンポーネントは、RPC メソッドを呼び出すときに ppStrNULL に設定する必要があります。