Associazione del contesto a un Flusso di dati
Per i callout che elaborano i dati a un livello di filtro che supporta i flussi di dati, il driver di callout può associare un contesto a ogni flusso di dati. Tale contesto è opaco al motore di filtro. La funzione di callout classificazioneFn del callout può usare questo contesto per salvare le informazioni sullo stato specifiche del flusso di dati per la successiva chiamata dal motore di filtro per tale flusso di dati. Il motore di filtro passa questo contesto alla funzione di callout di classificazioneFn del callout tramite il parametro flowContext . Se non è associato alcun contesto al flusso di dati, il parametro flowContext è zero.
Per associare un contesto a un flusso di dati, la funzione di callout classificazioneFn di un callout chiama la funzione FwpsFlowAssociateContext0 . Ad esempio:
// 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
...
}
}
}
...
}
Se un contesto è già associato a un flusso di dati, deve essere rimosso prima che un nuovo contesto possa essere associato al flusso di dati. Per rimuovere un contesto da un flusso di dati, la funzione di callout classificazioneFn di un callout chiama la funzione FwpsFlowRemoveContext0 . Ad esempio:
// 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
);
}
}
...
}
Negli esempi precedenti la variabile calloutId contiene l'identificatore di runtime per il callout. L'identificatore di runtime è lo stesso identificatore restituito al driver di callout quando il callout driver ha registrato il callout con il motore di filtro.