使用 __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是微型端口驱动程序定义的微型端口适配器上下文的句柄。 在微型端口驱动程序的上下文中,只应调用此函数一次。

__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 期间,将分配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) 字段 InterruptRegistered。

//
// 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;
    }

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