diff options
Diffstat (limited to 'network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp')
| -rw-r--r-- | network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp new file mode 100644 index 00000000..315dde6c --- /dev/null +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp @@ -0,0 +1,410 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2014 Microsoft Corporation. All Rights Reserved. +// +// Module Name: +// ClassifyFunctions_PendEndpointClosureCallouts.cpp +// +// Abstract: +// This module contains WFP Classify functions for pending and completing endpoint closures. +// +// Naming Convention: +// +// <Module><Scenario> +// +// i.e. +// +// ClassifyPendEndpointClosure +// +// <Module> +// Classify - Function is an FWPS_CALLOUT_CLASSIFY_FN. +// Perform - Function executes the desired scenario. +// Trigger - Function queues a worker thread for later execution of +// the the scenario. +// <Scenario> +// PendEndpointClosure - Function demonstates pending endpoint closure requests. +// +// Author: +// Dusty Harper (DHarper) +// +// Private Functions: +// PendEndpointClosureWorkItemRoutine(), +// PerformPendEndpointClosure(), +// TriggerPendEndpointClosureOutOfBand(), +// +// Public Functions: +// PendEndpointClosureDeferredProcedureCall(), +// ClassifyPendEndpointClosure(), +// +// Revision History: +// +// [ Month ][Day] [Year] - [Revision]-[ Comments ] +// December 13, 2013 - 1.1 - Creation +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "Framework_WFPSamplerCalloutDriver.h" /// . +#include "ClassifyFunctions_PendEndpointClosureCallouts.tmh" /// $(OBJ_PATH)\$(O)\ + +#if(NTDDI_VERSION >= NTDDI_WIN7) + +#pragma warning(push) +#pragma warning(disable: 6101) /// *ppPendData are freed and set to 0 on successful completion + +/** + @private_function="PerformPendEndpointClosure" + + Purpose: Waits for the specified delay, then completes the pended classify, and frees the + memory. <br> + <br> + Notes: <br> + <br> + MSDN_Ref: <br> +*/ +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +_IRQL_requires_same_ +_Success_(return == STATUS_SUCCESS) +NTSTATUS PerformPendEndpointClosure(_Inout_ PEND_DATA** ppPendData) +{ +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> PerformPendEndpointClosure()\n"); + +#endif /// DBG + + NT_ASSERT(*ppPendData); + NT_ASSERT((*ppPendData)->pPendEndpointClosureData); + + NTSTATUS status = STATUS_SUCCESS; + UINT32 delay = (*ppPendData)->pPendEndpointClosureData->delay; + + if(delay && + KeGetCurrentIrql() < DISPATCH_LEVEL) + { + +#pragma warning(push) +#pragma warning(disable: 28118) /// IRQL check has already been performed + + KrnlHlprWorkItemSleep(delay); + +#pragma warning(pop) + + } + +#pragma warning(push) +#pragma warning(disable: 6001) /// *ppPendData initialized prior to call to this function + + /// Completes the Pend + KrnlHlprPendDataDestroy(ppPendData); + +#pragma warning(pop) + +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " <--- PerformPendEndpointClosure() [status: %#x]\n", + status); + +#endif /// DBG + + return status; +}; + +#pragma warning(pop) + +/** + @private_function="PendEndpointClosureDeferredProcedureCall" + + Purpose: Invokes the appropriate private routine to complete the pended classify. <br> + <br> + Notes: <br> + <br> + MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF542972.aspx <br> +*/ +_IRQL_requires_(DISPATCH_LEVEL) +_IRQL_requires_same_ +_Function_class_(KDEFERRED_ROUTINE) +VOID PendEndpointClosureDeferredProcedureCall(_In_ KDPC* pDPC, + _In_opt_ PVOID pContext, + _In_opt_ PVOID pArg1, + _In_opt_ PVOID pArg2) +{ +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> PendEndpointClosureDeferredProcedureCall()\n"); + +#endif /// DBG + + UNREFERENCED_PARAMETER(pDPC); + UNREFERENCED_PARAMETER(pContext); + UNREFERENCED_PARAMETER(pArg2); + + NT_ASSERT(pDPC); + NT_ASSERT(pArg1); + NT_ASSERT(((DPC_DATA*)pArg1)->pPendData); + + DPC_DATA* pDPCData = (DPC_DATA*)pArg1; + + if(pDPCData) + { + NTSTATUS status = STATUS_SUCCESS; + + status = PerformPendEndpointClosure(&(pDPCData->pPendData)); + if(status != STATUS_SUCCESS) + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_ERROR_LEVEL, + " !!!! PendEndpointClosureDeferredProcedureCall() [status: %#x]\n", + status); + + KrnlHlprDPCDataDestroy(&pDPCData); + } + +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " <--- PendEndpointClosureDeferredProcedureCall()\n"); + +#endif /// DBG + + return; +} + +/** + @private_function="PendEndpointClosureWorkItemRoutine" + + Purpose: Invokes the appropriate private routine to complete the pended classify at + PASSIVE_LEVEL. <br> + <br> + Notes: <br> + <br> + MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF566380.aspx <br> +*/ +_IRQL_requires_(PASSIVE_LEVEL) +_IRQL_requires_same_ +_Function_class_(IO_WORKITEM_ROUTINE) +VOID PendEndpointClosureWorkItemRoutine(_In_ PDEVICE_OBJECT pDeviceObject, + _In_opt_ PVOID pContext) +{ +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> PendEndpointClosureWorkItemRoutine()\n"); + +#endif /// DBG + + UNREFERENCED_PARAMETER(pDeviceObject); + + NT_ASSERT(pContext); + NT_ASSERT(((WORKITEM_DATA*)pContext)->pPendData); + + WORKITEM_DATA* pWorkItemData = (WORKITEM_DATA*)pContext; + + if(pWorkItemData) + { + NTSTATUS status = STATUS_SUCCESS; + + status = PerformPendEndpointClosure(&(pWorkItemData->pPendData)); + if(status != STATUS_SUCCESS) + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_ERROR_LEVEL, + " !!!! PendEndpointClosureWorkItemRoutine() [status: %#x]\n", + status); + + KrnlHlprWorkItemDataDestroy(&pWorkItemData); + } + +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " <--- PendEndpointClosureWorkItemRoutine()\n"); + +#endif /// DBG + + return; +} + +/** + @private_function="TriggerPendEndpointClosure" + + Purpose: <br> + <br> + Notes: <br> + <br> + MSDN_Ref: <br> +*/ +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +_IRQL_requires_same_ +_Success_(return == STATUS_SUCCESS) +NTSTATUS TriggerPendEndpointClosure(_Inout_ PEND_DATA* pPendData, + _In_ PC_PEND_ENDPOINT_CLOSURE_DATA* pPCData) +{ +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> TriggerPendEndpointClosure()\n"); + +#endif /// DBG + + NT_ASSERT(pPendData); + NT_ASSERT(pPCData); + + NTSTATUS status = STATUS_SUCCESS; + + if(pPCData->useWorkItems || + pPCData->delay) + { + /// introducing the delay requires PASSIVE_LEVEL, so force use of a Work Item + status = KrnlHlprWorkItemQueue(g_pWDMDevice, + PendEndpointClosureWorkItemRoutine, + pPendData); + } + else + { + if(pPCData->useThreadedDPC) + status = KrnlHlprThreadedDPCQueue(PendEndpointClosureDeferredProcedureCall, + pPendData); + else + status = KrnlHlprDPCQueue(PendEndpointClosureDeferredProcedureCall, + pPendData); + } + +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " <--- TriggerPendEndpointClosure() [status: %#x]\n", + status); + +#endif /// DBG + + return status; +} + +/** + @classify_function="ClassifyPendEndpointClosure" + + Purpose: Classify Function which will pend an endpoint closure request. If there is + appropriate flowContext, te request will be pended, and then exit, requiring a call + to the FlowDeleteFn to perform the pend completion. Otherwise a worker thread is + queued, and a will wait for the specified milliseconds before the pend is + completed. <br> + <br> + Notes: Applies to the following layers: <br> + FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V{4/6} <br> + <br> + MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF551229.aspx <br> + HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF544893.aspx <br> +*/ +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +_IRQL_requires_same_ +VOID NTAPI ClassifyPendEndpointClosure(_In_ const FWPS_INCOMING_VALUES* pClassifyValues, + _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, + _Inout_opt_ VOID* pLayerData, + _In_opt_ const VOID* pClassifyContext, + _In_ const FWPS_FILTER* pFilter, + _In_ UINT64 flowContext, + _Inout_ FWPS_CLASSIFY_OUT* pClassifyOut) +{ + NT_ASSERT(pClassifyValues); + NT_ASSERT(pMetadata); + NT_ASSERT(pFilter); + NT_ASSERT(pClassifyOut); + NT_ASSERT(pClassifyValues->layerId == FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V4 || + pClassifyValues->layerId == FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V6); + NT_ASSERT(pFilter->providerContext); + NT_ASSERT(pFilter->providerContext->type == FWPM_GENERAL_CONTEXT); + NT_ASSERT(pFilter->providerContext->dataBuffer); + NT_ASSERT(pFilter->providerContext->dataBuffer->size == sizeof(PC_PEND_ENDPOINT_CLOSURE_DATA)); + NT_ASSERT(pFilter->providerContext->dataBuffer->data); + + UNREFERENCED_PARAMETER(pLayerData); + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> ClassifyPendEndpointClosure() [Layer: %s][FilterID: %#I64x][FlowContext: %#I64x][Rights: %#x]", + KrnlHlprFwpsLayerIDToString(pClassifyValues->layerId), + pFilter->filterId, + flowContext, + pClassifyOut->rights); + + NTSTATUS status = STATUS_SUCCESS; + PEND_DATA* pPendData = 0; + +#pragma warning(push) +#pragma warning(disable: 6014) /// pPendData will be freed in PerformPendEndpointClosure + + status = KrnlHlprPendDataCreate(&pPendData, + pClassifyValues, + pMetadata, + 0, + pFilter, + (VOID*)pClassifyContext, + pClassifyOut); + HLPR_BAIL_ON_FAILURE(status); + +#pragma warning(pop) + + if(flowContext) + { + NT_ASSERT(flowContext); + NT_ASSERT(((FLOW_CONTEXT*)flowContext)->contextType == CONTEXT_TYPE_ALE_ENDPOINT_CLOSURE); + NT_ASSERT(((FLOW_CONTEXT*)flowContext)->pALEEndpointClosureContext); + + FLOW_CONTEXT* pFlowContext = (FLOW_CONTEXT*)flowContext; + KIRQL irql = PASSIVE_LEVEL; + + KeAcquireSpinLock(&(pFlowContext->pALEEndpointClosureContext->spinLock), + &irql); + + /// NotifyFlowDeleteNotification will free this memory + pFlowContext->pALEEndpointClosureContext->pPendData = pPendData; + pFlowContext->pALEEndpointClosureContext->filterID = pFilter->filterId; + + KeReleaseSpinLock(&(pFlowContext->pALEEndpointClosureContext->spinLock), + irql); + } + else + { + PC_PEND_ENDPOINT_CLOSURE_DATA* pPendEndpointClosureData = (PC_PEND_ENDPOINT_CLOSURE_DATA*)pFilter->providerContext->dataBuffer->data; + + status = TriggerPendEndpointClosure(pPendData, + pPendEndpointClosureData); + } + + HLPR_BAIL_LABEL: + + if(status != STATUS_SUCCESS) + { + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_ERROR_LEVEL, + " !!!! ClassifyPendEndpointClosure() [status: %#x]\n", + status); + + KrnlHlprPendDataDestroy(&pPendData); + } + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " <--- ClassifyPendEndpointClosure() [Layer: %s][FilterID: %#I64x][Action: %#x][Rights: %#x][Absorb: %s]\n", + KrnlHlprFwpsLayerIDToString(pClassifyValues->layerId), + pFilter->filterId, + pClassifyOut->actionType, + pClassifyOut->rights, + (pClassifyOut->flags & FWPS_CLASSIFY_OUT_FLAG_ABSORB) ? "TRUE" : "FALSE"); + + return; +} + +#endif /// (NTDDI_VERSION >= NTDDI_WIN7) |
