Share via


アダプター コンテキスト フィールドを追跡するための __sdv_save_adapter_context の使用

NDIS ミニポート ドライバーの MiniportInitializeEx コールバック関数を呼び出してミニポート アダプターを初期化する場合、ドライバーは、ミニポート アダプターを表す独自の内部データ構造を作成します。 ドライバーは、ミニポート アダプターコンテキストと呼ばれるこの構造体を使用して、ミニポート アダプターを管理するためにドライバーが必要とするデバイス固有の状態情報をメインします。 ドライバーは、NDIS にこの構造体にハンドルを渡します。

NDIS は、ミニポート アダプターに関連するミニポート ドライバーの MiniportXxx 関数のいずれかを呼び出すと、NDIS は、ドライバーに正しいミニポート アダプターを識別するミニポート アダプター のコンテキストを渡します。 ミニポート アダプター コンテキストは所有メインミニポート ドライバーによって保持され、NDIS とプロトコル ドライバーに不透明です。

ミニポート アダプター コンテキストメイン NDIS 呼び出しの間にミニポート ドライバーの状態が含まれているため、静的ドライバー検証ツール (SDV) は、この構造体へのポインターを識別できる必要があります。 ミニポート ドライバーの状態を追跡する SDV を有効にするには、__sdv_save_adapter_context 関数を使用してミニポート アダプター コンテキストにハンドルを保存する必要があります。

__sdv_save_adapter_context関数には、次の構文があります。

__sdv_save_adapter_context( &adapter_context ) 

ここでadapter_contextは、ミニポート ドライバーによって定義されているミニポート アダプター コンテキストへのハンドルです。 この関数は、ミニポート ドライバーのコンテキストで 1 回だけ呼び出す必要があります。

__sdv_save_adapter_context関数は、静的分析ツールでのみ使用されます。 この関数はコンパイラによって無視されます。

次のコード例は、__sdv_save_adapter_contextを呼び出すタイミングと、SDV がミニポート アダプター コンテキストで情報を追跡する方法を示しています。

次のコード例は、ミニポート アダプター コンテキストのサンプル構造の簡略化されたバージョンである MP_Adapter を示します。

typedef struct _MP_ADAPTER
{
    NDIS_HANDLE             AdapterHandle;

    BOOLEAN                 InterruptRegistered;
    NDIS_HANDLE             InterruptHandle;

    /* ..................... */

} MP_ADAPTER, *PMP_ADAPTER;

MiniportInitializeExミニポートInitializeEx の実行中に、MP_ADAPER構造体のメモリが割り当てられます。 メモリ割り当ての直後に、 __sdv_save_adapter_context が呼び出されます。

ミニポート アダプター コンテキスト 構造への有効なポインターがある場合は、すぐに __sdv_save_adapter_context 関数を呼び出す必要があります。

NDIS_STATUS 
MPInitialize(
    IN  NDIS_HANDLE                        MiniportAdapterHandle,
    IN  NDIS_HANDLE                        MiniportDriverContext,
    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
    )
{
    NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
    PMP_ADAPTER     pAdapter = NULL;
 
    /* ..................... */
 
    do
    {
   // allocate the memory for the AdapterContext
        pAdapter = NdisAllocateMemoryWithTagPriority(
            MiniportAdapterHandle,
            sizeof(MP_ADAPTER),
            NIC_TAG,
            LowPoolPriority
            );

   // save the adapter context, even before we check whether it is NULL or not 
 __sdv_save_adapter_context(&pAdapter);

        if (pAdapter == NULL)
        {
            Status = NDIS_STATUS_RESOURCES;
            break;
        }
 
        NdisZeroMemory(pAdapter, sizeof(MP_ADAPTER));
 
        pAdapter->AdapterHandle = MiniportAdapterHandle;
        pAdapter->PauseState = NicPaused;

   /* ..................... */

次のコード例は、SDV がミニポート アダプターコンテキストで値を追跡する方法を示しています。 この例では、ドライバーはミニポート提供の関数 MpRegisterInterrupt を呼び出すことによって割り込みを登録します。 呼び出しが成功した場合、ドライバーは、ミニポート アダプター コンテキスト (pAdapter) フィールドに結果を保存、割り込み登録します。

//
// Register the interrupt
   //
        Status = MpRegisterInterrupt(pAdapter);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }
 
   // save the value of the result into the AdapterContext
        pAdapter->InterruptRegistered = TRUE;

ミニポート ドライバーを停止する必要がある場合、NDIS はミニポート アダプター コンテキストにハンドルを渡すことによって、ドライバーの MiniportHaltEx 関数を呼び出します。 SDV にもこのハンドルがあるため、以前の呼び出しから __sdv_save_adapter_context まで、SDV は InterruptRegistered フィールドの値を追跡できます。

VOID MPHalt(
    IN  NDIS_HANDLE             MiniportAdapterContext,
    IN  NDIS_HALT_ACTION        HaltAction
    )
{
    PMP_ADAPTER     pAdapter = (PMP_ADAPTER) MiniportAdapterContext;
 
    /* ..................... */

    if (pAdapter->InterruptRegistered)
    {
        NdisMDeregisterInterruptEx(pAdapter->InterruptHandle);
        pAdapter->InterruptRegistered = FALSE;
    }

/* ..................... */