컨텍스트를 Data Flow 연결

데이터 흐름을 지원하는 필터링 계층에서 데이터를 처리하는 설명선의 경우 설명선 드라이버는 컨텍스트를 각 데이터 흐름과 연결할 수 있습니다. 이러한 컨텍스트는 필터 엔진에 불투명합니다. 설명선의 classifyFn 설명선 함수는 이 컨텍스트를 사용하여 다음에 해당 데이터 흐름에 대한 필터 엔진에서 호출할 때 데이터 흐름과 관련된 상태 정보를 저장할 수 있습니다. 필터 엔진은 flowContext 매개 변수를 통해 이 컨텍스트를 설명선의 classifyFn 설명선 함수에 전달합니다. 데이터 흐름과 연결된 컨텍스트가 없는 경우 flowContext 매개 변수는 0입니다.

컨텍스트를 데이터 흐름과 연결하기 위해 설명선의 classifyFn 설명선 함수는 FwpsFlowAssociateContext0 함수를 호출합니다. 예:

// Context structure to be associated with data flows
typedef struct FLOW_CONTEXT_ {
  .
  .  // Driver-specific content
  .
} FLOW_CONTEXT, *PFLOW_CONTEXT;

#define FLOW_CONTEXT_POOL_TAG 'fcpt'

// classifyFn callout function
VOID NTAPI
 ClassifyFn(
    IN const FWPS_INCOMING_VALUES0  *inFixedValues,
    IN const FWPS_INCOMING_METADATA_VALUES0  *inMetaValues,
    IN OUT VOID  *layerData,
    IN const FWPS_FILTER0  *filter,
    IN UINT64  flowContext,
    IN OUT FWPS_CLASSIFY_OUT  *classifyOut
  )
{
  PFLOW_CONTEXT context;
  UINT64 flowHandle;
  NTSTATUS status;

  ...

  // Check for the flow handle in the metadata
  if (FWPS_IS_METADATA_FIELD_PRESENT(
      inMetaValues,
      FWPS_METADATA_FIELD_FLOW_HANDLE))
  {
    // Get the flow handle
    flowHandle = inMetaValues->flowHandle;

    // Allocate the flow context structure
    context =
      (PFLOW_CONTEXT)ExAllocatePoolWithTag(
        NonPagedPool,
        sizeof(FLOW_CONTEXT),
        FLOW_CONTEXT_POOL_TAG
      );

    // Check the result of the memory allocation
    if (context == NULL) 
    {
 
      // Handle memory allocation error
      ...
    }
    else
    {

      // Initialize the flow context structure
      ...

      // Associate the flow context structure with the data flow
      status = FwpsFlowAssociateContext0(
                flowHandle,
                FWPS_LAYER_STREAM_V4,
                calloutId,
                (UINT64)context
              );

      // Check the result
      if (status != STATUS_SUCCESS)
      {
        // Handle error
        ...
      }
    }
  }

  ...

}

컨텍스트가 이미 데이터 흐름과 연결된 경우 먼저 새 컨텍스트를 데이터 흐름과 연결하기 전에 해당 컨텍스트를 제거해야 합니다. 데이터 흐름에서 컨텍스트를 제거하기 위해 설명선의 classifyFn 설명선 함수는 FwpsFlowRemoveContext0 함수를 호출합니다. 예:

// Context structure to be associated with data flows
typedef struct FLOW_CONTEXT_ {
  ...
} FLOW_CONTEXT, *PFLOW_CONTEXT;

#define FLOW_CONTEXT_POOL_TAG 'fcpt'

// classifyFn callout function
VOID NTAPI
 ClassifyFn(
    IN const FWPS_INCOMING_VALUES0  *inFixedValues,
    IN const FWPS_INCOMING_METADATA_VALUES0  *inMetaValues,
    IN OUT VOID  *layerData,
    IN const FWPS_FILTER0  *filter,
    IN UINT64  flowContext,
    OUT FWPS_CLASSIFY_OUT  *classifyOut
  )
{
  PFLOW_CONTEXT context;
  UINT64 flowHandle;
  NTSTATUS status;

  ...

  // Check for the flow handle in the metadata
 if (FWPS_IS_METADATA_FIELD_PRESENT(
    inMetaValues,
    FWPS_METADATA_FIELD_FLOW_HANDLE))
  {
    // Get the flow handle
     flowHandle = inMetaValues->flowHandle;

    // Check whether there is a context associated with the data flow
     if (flowHandle != 0) 
     {
        // Get a pointer to the flow context structure
        context = (PFLOW_CONTEXT)flowContext;

        // Remove the flow context structure from the data flow
        status = FwpsFlowRemoveContext0(
                  flowHandle,
                  FWPS_LAYER_STREAM_V4,
                  calloutId
                );

      // Check the result
      if (status != STATUS_SUCCESS)
      {
        // Handle error
        ...
      }

      // Cleanup the flow context structure
      ...

      // Free the memory for the flow context structure
      ExFreePoolWithTag(
        context,
        FLOW_CONTEXT_POOL_TAG
        );
    }
  }

  ...

}

이전 예제에서 calloutId 변수는 설명선에 대한 런타임 식별자를 포함합니다. 런타임 식별자는 콜아웃 드라이버가 필터 엔진에 콜아웃을 등록할 때 콜아웃 드라이버에 반환된 것과 동일한 식별자입니다.