Asociación de contexto con un Data Flow
En el caso de las llamadas que procesan datos en una capa de filtrado que admite flujos de datos, el controlador de llamada puede asociar un contexto a cada flujo de datos. Este contexto es opaco para el motor de filtros. La función de llamada classifyFn de la llamada puede usar este contexto para guardar información de estado específica del flujo de datos para la próxima vez que el motor de filtros llame a él para ese flujo de datos. El motor de filtros pasa este contexto a la función de llamada classifyFn de la llamada a través del parámetro flowContext . Si no hay ningún contexto asociado al flujo de datos, el parámetro flowContext es cero.
Para asociar un contexto a un flujo de datos, la función de llamada classifyFn de una llamada llama a la función FwpsFlowAssociateContext0 . Por ejemplo:
// 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 contexto ya está asociado a un flujo de datos, primero debe quitarse antes de que se pueda asociar un nuevo contexto al flujo de datos. Para quitar un contexto de un flujo de datos, la función de llamada classifyFn de una llamada llama a la función FwpsFlowRemoveContext0 . Por ejemplo:
// 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
);
}
}
...
}
En los ejemplos anteriores, la variable calloutId contiene el identificador en tiempo de ejecución de la llamada. El identificador en tiempo de ejecución es el mismo identificador que se devolvió al controlador de llamada cuando el controlador de llamada registró la llamada con el motor de filtro.