Association d’un contexte à un Data Flow
Pour les légendes qui traitent des données au niveau d’une couche de filtrage prenant en charge les flux de données, le pilote de légende peut associer un contexte à chaque flux de données. Un tel contexte est opaque pour le moteur de filtre. La fonction de légende classifyFn de la légende peut utiliser ce contexte pour enregistrer les informations d’état spécifiques au flux de données pour la prochaine fois qu’il sera appelé par le moteur de filtre pour ce flux de données. Le moteur de filtre transmet ce contexte à la fonction de légende classFn de la légende via le paramètre flowContext . Si aucun contexte n’est associé au flux de données, le paramètre flowContext est égal à zéro.
Pour associer un contexte à un flux de données, la fonction de légende classifyFn d’une légende appelle la fonction FwpsFlowAssociateContext0 . Par exemple :
// 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
...
}
}
}
...
}
Si un contexte est déjà associé à un flux de données, il doit d’abord être supprimé avant qu’un nouveau contexte puisse être associé au flux de données. Pour supprimer un contexte d’un flux de données, la fonction de légende classifyFn d’une légende appelle la fonction FwpsFlowRemoveContext0 . Par exemple :
// 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
);
}
}
...
}
Dans les exemples précédents, la variable calloutId contient l’identificateur d’exécution de la légende. L’identificateur d’exécution est le même identificateur que celui qui a été retourné au pilote de légende lorsque le pilote de légende a inscrit la légende auprès du moteur de filtre.