Zuordnen von Kontext zu einem Datenfluss

Für Legenden, die Daten auf einer Filterebene verarbeiten, die Datenflüsse unterstützt, kann der Legendentreiber jedem Datenfluss einen Kontext zuordnen. Ein solcher Kontext ist für die Filter-Engine undurchsichtig. Die Legendenfunktion klassifizierenFn der Legende kann diesen Kontext verwenden, um Zustandsinformationen zu speichern, die für den Datenfluss spezifisch sind, wenn sie das nächste Mal vom Filtermodul für diesen Datenfluss aufgerufen wird. Die Filter-Engine übergibt diesen Kontext über den flowContext-Parameter an die Beschriftungsfunktion klassifizierenFn. Wenn dem Datenfluss kein Kontext zugeordnet ist, ist der flowContext-Parameter 0.

Um einen Kontext einem Datenfluss zuzuordnen, ruft die Calloutfunktion klassifizierenFn die Funktion FwpsFlowAssociateContext0 auf. Beispiel:

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

  ...

}

Wenn ein Kontext bereits einem Datenfluss zugeordnet ist, muss er zuerst entfernt werden, bevor dem Datenfluss möglicherweise ein neuer Kontext zugeordnet wird. Um einen Kontext aus einem Datenfluss zu entfernen, ruft die Calloutfunktion klassifizierenFn die Funktion FwpsFlowRemoveContext0 auf. Beispiel:

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

  ...

}

In den vorherigen Beispielen enthält die variable calloutId den Laufzeitbezeichner für die Legende. Der Laufzeitbezeichner ist derselbe Bezeichner, der an den Legendentreiber zurückgegeben wurde, als der Legendentreiber die Legende beim Filtermodul registriert hat.