NTSTATUS KrnlHlprClassifyDataAcquireLocalCopy(_Inout_ CLASSIFY_DATA* pClassifyData, _In_ const FWPS_INCOMING_VALUES* pClassifyValues, _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, _In_opt_ VOID* pPacket, _In_opt_ const VOID* pClassifyContext, _In_ const FWPS_FILTER* pFilter, _In_ const UINT64 flowContext, _In_ FWPS_CLASSIFY_OUT* pClassifyOut) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprClassifyDataAcquireLocalCopy()\n"); #endif /// DBG NT_ASSERT(pClassifyData); NT_ASSERT(pClassifyValues); NT_ASSERT(pMetadata); NT_ASSERT(pFilter); NT_ASSERT(pClassifyOut); NTSTATUS status = STATUS_SUCCESS; pClassifyData->pClassifyValues = KrnlHlprFwpsIncomingValuesCreateLocalCopy(pClassifyValues); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pClassifyValues, status); pClassifyData->pMetadataValues = KrnlHlprFwpsIncomingMetadataValuesCreateLocalCopy(pMetadata); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pMetadataValues, status); if(pPacket) { if(pClassifyValues->layerId == FWPS_LAYER_STREAM_V4 || pClassifyValues->layerId == FWPS_LAYER_STREAM_V4_DISCARD || pClassifyValues->layerId == FWPS_LAYER_STREAM_V6 || pClassifyValues->layerId == FWPS_LAYER_STREAM_V6_DISCARD) { pClassifyData->pPacket = KrnlHlprFwpsStreamCalloutIOPacketCreateLocalCopy((FWPS_STREAM_CALLOUT_IO_PACKET*)pPacket); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pPacket, status); } #if(NTDDI_VERSION >= NTDDI_WIN7) /// LayerData at the FWPM_LAYER_ALE_{BIND/CONNECT}_REDIRECT_V{4/6} is obtained via KrnlHlprRedirectDataCreate() else if(pClassifyValues->layerId == FWPS_LAYER_ALE_CONNECT_REDIRECT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_CONNECT_REDIRECT_V6 || pClassifyValues->layerId == FWPS_LAYER_ALE_BIND_REDIRECT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_BIND_REDIRECT_V6) { pClassifyData->pPacket = 0; } #endif /// (NTDDI_VERSION >= NTDDI_WIN7) else { if(NET_BUFFER_LIST_NEXT_NBL((NET_BUFFER_LIST*)pPacket)) { pClassifyData->chainedNBL = TRUE; pClassifyData->numChainedNBLs = 1; } if(pClassifyData->chainedNBL && ( /// The IPPACKET and IPFORWARD Layers allow for Fragment Grouping if the option is enabled pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V4 || pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V6 || pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V4 || pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V6 #if(NTDDI_VERSION >= NTDDI_WIN8) /// The NDIS layers allow for batched NBLs provided the callout was registered with FWP_CALLOUT_FLAG_ALLOW_L2_BATCH_CLASSIFY set || pClassifyValues->layerId == FWPS_LAYER_INBOUND_MAC_FRAME_ETHERNET || pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_MAC_FRAME_ETHERNET || pClassifyValues->layerId == FWPS_LAYER_INBOUND_MAC_FRAME_NATIVE || pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_MAC_FRAME_NATIVE || pClassifyValues->layerId == FWPS_LAYER_INGRESS_VSWITCH_ETHERNET || pClassifyValues->layerId == FWPS_LAYER_EGRESS_VSWITCH_ETHERNET #endif /// (NTDDI_VERSION >= NTDDI_WIN8) )) { for(NET_BUFFER_LIST* pCurrentNBL = (NET_BUFFER_LIST*)pPacket; pCurrentNBL; pClassifyData->numChainedNBLs++) { NET_BUFFER_LIST* pNextNBL = NET_BUFFER_LIST_NEXT_NBL(pCurrentNBL); FwpsReferenceNetBufferList(pCurrentNBL, TRUE); pCurrentNBL = pNextNBL; #if DBG InterlockedIncrement64((LONG64*)&(g_OutstandingNBLReferences)); #endif /// DBG } pClassifyData->pPacket = pPacket; } else { /// Otherwise we expect to receive a single NBL NT_ASSERT(NET_BUFFER_LIST_NEXT_NBL((NET_BUFFER_LIST*)pPacket) == 0); FwpsReferenceNetBufferList((NET_BUFFER_LIST*)pPacket, TRUE); pClassifyData->pPacket = pPacket; #if DBG InterlockedIncrement64((LONG64*)&(g_OutstandingNBLReferences)); #endif /// DBG } } } #if(NTDDI_VERSION >= NTDDI_WIN7) if(pClassifyContext) { /// ClassifyHandle for these layers is obtained in REDIRECT_DATA if(pClassifyValues->layerId != FWPS_LAYER_ALE_CONNECT_REDIRECT_V4 && pClassifyValues->layerId != FWPS_LAYER_ALE_CONNECT_REDIRECT_V6 && pClassifyValues->layerId != FWPS_LAYER_ALE_BIND_REDIRECT_V4 && pClassifyValues->layerId != FWPS_LAYER_ALE_BIND_REDIRECT_V6) { status = FwpsAcquireClassifyHandle((VOID*)pClassifyContext, 0, &(pClassifyData->classifyContextHandle)); HLPR_BAIL_ON_FAILURE(status); } } #else UNREFERENCED_PARAMETER(pClassifyContext); #endif /// (NTDDI_VERSION >= NTDDI_WIN7) if(pFilter) { pClassifyData->pFilter = KrnlHlprFwpsFilterCreateLocalCopy(pFilter); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pFilter, status); } pClassifyData->flowContext = flowContext; if(pClassifyOut) { pClassifyData->pClassifyOut = KrnlHlprFwpsClassifyOutCreateLocalCopy(pClassifyOut); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pClassifyOut, status); } HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) KrnlHlprClassifyDataReleaseLocalCopy(pClassifyData); #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- KrnlHlprClassifyDataAcquireLocalCopy() [status: %#x]\n", status); #endif /// DBG return status; }
NTSTATUS KrnlHlprRedirectDataPopulate(_Inout_ REDIRECT_DATA* pRedirectData, _In_ const VOID* pClassifyContext, _In_ const FWPS_FILTER* pFilter, _In_ FWPS_CLASSIFY_OUT* pClassifyOut) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprRedirectDataPopulate()\n"); #endif /// DBG NT_ASSERT(pRedirectData); NT_ASSERT(pClassifyContext); NT_ASSERT(pFilter); NT_ASSERT(pClassifyOut); 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_PROXY_DATA)); NT_ASSERT(pFilter->providerContext->dataBuffer->data); NTSTATUS status = STATUS_SUCCESS; status = FwpsAcquireClassifyHandle((void*)pClassifyContext, 0, &(pRedirectData->classifyHandle)); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprRedirectDataPopulate : FwpsAcquireClassifyHandle() [status: %#x]\n", status); HLPR_BAIL; } #if(NTDDI_VERSION >= NTDDI_WIN8) status = FwpsRedirectHandleCreate(&WFPSAMPLER_PROVIDER, 0, &(pRedirectData->redirectHandle)); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprRedirectDataPopulate : FwpsRedirectHandleCreate() [status: %#x]\n", status); HLPR_BAIL; } #endif status = FwpsAcquireWritableLayerDataPointer(pRedirectData->classifyHandle, pFilter->filterId, 0, &(pRedirectData->pWritableLayerData), pClassifyOut); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprRedirectDataPopulate : FwpsAcquireWritableLayerDataPointer() [status: %#x]\n", status); HLPR_BAIL; } pRedirectData->pProxyData = (PC_PROXY_DATA*)pFilter->providerContext->dataBuffer->data; HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) KrnlHlprRedirectDataPurge(pRedirectData); #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- KrnlHlprRedirectDataPopulate() [status: %#x]\n", status); #endif /// DBG return status; }
NTSTATUS KrnlHlprPendDataPopulate(_Inout_ PEND_DATA* pPendData, _In_ const FWPS_INCOMING_VALUES* pClassifyValues, _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, _In_opt_ NET_BUFFER_LIST* pNBL, _In_ const FWPS_FILTER* pFilter, _In_opt_ VOID* pClassifyContext, /* 0 */ _In_opt_ FWPS_CLASSIFY_OUT* pClassifyOut) /* 0 */ { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprPendDataPopulate()\n"); #endif /// DBG NT_ASSERT(pPendData); NT_ASSERT(pClassifyValues); NT_ASSERT(pMetadata); NT_ASSERT(pFilter); NTSTATUS status = STATUS_SUCCESS; pPendData->layerID = pClassifyValues->layerId; #if(NTDDI_VERSION >= NTDDI_WIN7) if(pPendData->layerID == FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V4 || pPendData->layerID == FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V6) { NT_ASSERT(pClassifyContext); NT_ASSERT(pClassifyOut); if(pClassifyContext && pClassifyOut) { status = FwpsAcquireClassifyHandle(pClassifyContext, 0, &(pPendData->classifyHandle)); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprPendDataPopulate : FwpsAcquireClassifyHandle() [status: %#x]\n", status); HLPR_BAIL; } status = FwpsPendClassify(pPendData->classifyHandle, pFilter->filterId, 0, pClassifyOut); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprPendDataPopulate : FwpsPendClassify() [status: %#x]\n", status); HLPR_BAIL; } RtlCopyMemory(&(pPendData->classifyOut), pClassifyOut, sizeof(FWPS_CLASSIFY_OUT)); pPendData->pPCPendData = pFilter->providerContext->dataBuffer->data; pPendData->isPended = TRUE; } else { status = STATUS_INVALID_PARAMETER; DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprPendDataPopulate : [status: %#x][pClassifyContext: %#p][pClassifyOut: %#p]\n", status, pClassifyContext, pClassifyOut); HLPR_BAIL; } } else #else UNREFERENCED_PARAMETER(pClassifyContext); UNREFERENCED_PARAMETER(pClassifyOut); #endif /// (NTDDI_VERSION >= NTDDI_WIN7) { if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata, FWPS_METADATA_FIELD_COMPLETION_HANDLE)) { status = FwpsPendOperation(pMetadata->completionHandle, &(pPendData->completionContext)); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprPendDataPopulate : FwpsPendOperation() [status: %#x]\n", status); HLPR_BAIL; } pPendData->pNBL = pNBL; pPendData->pPCPendData = pFilter->providerContext->dataBuffer->data; pPendData->isPended = TRUE; } else { status = STATUS_INVALID_HANDLE; DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprPendDataPopulate() [status: %#x]\n", status); } } HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) KrnlHlprPendDataPurge(pPendData); #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- KrnlHlprPendDataPopulate() [status: %#x]\n", status); #endif /// DBG return status; }