//////////////////////////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2014 Microsoft Corporation. All Rights Reserved. // // Module Name: // Framework_WFPSamplerCalloutDriver.cpp // // Abstract: // // Author: // Dusty Harper (DHarper) // // Revision History: // // [ Month ][Day] [Year] - [Revision]-[ Comments ] // May 01, 2010 - 1.0 - Creation // December 13, 2013 - 1.1 - Add support for multiple injectors and redirectors, and // add support for serializing asynchronous // FWPM_LAYER_STREAM injections // //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . #include "Framework_Include.h" /// . #include "Framework_WFPSamplerCalloutDriver.tmh" /// $(OBJ_PATH)\$(O)\ extern "C" { _IRQL_requires_(PASSIVE_LEVEL) _IRQL_requires_same_ _Function_class_(DRIVER_INITIALIZE) DRIVER_INITIALIZE DriverEntry; }; PDEVICE_OBJECT g_pWDMDevice = 0; PIO_WORKITEM g_pPowerStateEnterIOWorkItem = 0; PIO_WORKITEM g_pPowerStateExitIOWorkItem = 0; NDIS_POOL_DATA* g_pNDISPoolData = 0; BOOLEAN g_calloutsRegistered = FALSE; HANDLE g_bfeSubscriptionHandle = 0; SERIALIZATION_LIST g_bsiSerializationList = {0}; WFPSAMPLER_DEVICE_DATA g_WFPSamplerDeviceData = {0}; DEVICE_EXTENSION g_deviceExtension = {0}; KSPIN_LOCK g_bpeSpinLock; WDFDRIVER g_WDFDriver; WDFDEVICE g_WDFDevice; /** @private_function="PrvBasicStreamInjectionSerializationListInitialization" Purpose: Initialize Stream Injection's global serailization list.

Notes:

MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF552160.aspx
HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF551171.aspx
HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF547799.aspx
*/ _Success_(return == STATUS_SUCCESS) NTSTATUS PrvBasicStreamInjectionSerializationListInitialization() { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> PrvBasicStreamInjectionSerializationListInitialization()\n"); #endif /// DBG NTSTATUS status = STATUS_SUCCESS; KeInitializeSpinLock(&(g_bsiSerializationList.spinLock)); status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &(g_bsiSerializationList.waitLock)); HLPR_BAIL_ON_FAILURE(status); InitializeListHead(&(g_bsiSerializationList.listHead)); g_bsiSerializationList.numEntries = 0; HLPR_BAIL_LABEL: #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- PrvBasicStreamInjectionSerializationListInitialization() [status: %#x]", status); #endif /// DBG return status; } /** @private_function="PrvFwpmBfeStateSubscribeChanges" Purpose: Subscribe to notifications of changes to the BFE service's state.

Notes:

MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF550062.aspx
*/ _Success_(return == STATUS_SUCCESS) NTSTATUS PrvFwpmBfeStateSubscribeChanges() { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> PrvFwpmBfeStateSubscribeChanges()\n"); #endif /// DBG NTSTATUS status = STATUS_SUCCESS; status = FwpmBfeStateSubscribeChanges(g_pWDMDevice, SubscriptionBFEStateChangeCallback, &g_WFPSamplerDeviceData, &g_bfeSubscriptionHandle); if(status != STATUS_SUCCESS) DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! PrvFwpmBfeStateSubscribeChanges : FwpmBfeStateSubscribeChanges() [status: %#x]\n", status); #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- PrvFwpmBfeStateSubscribeChanges() [status: %#x]\n", status); #endif /// DBG return status; } /** @private_function="PrvWFPSamplerDeviceDataPopulate" Purpose: Register the global WFP objects such as:
Callouts

Notes:

MSDN_Ref:
*/ _IRQL_requires_(PASSIVE_LEVEL) _IRQL_requires_same_ _Check_return_ _Success_(return == STATUS_SUCCESS) NTSTATUS PrvWFPSamplerFwpObjectsAddGlobal(_In_ WFPSAMPLER_DEVICE_DATA* pDeviceData) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> PrvWFPSamplerFwpObjectsAddGlobal()\n"); #endif /// DBG UNREFERENCED_PARAMETER(pDeviceData); NT_ASSERT(pDeviceData); NTSTATUS status = STATUS_SUCCESS; if(g_calloutsRegistered == FALSE) { status = KrnlHlprExposedCalloutsRegister(); HLPR_BAIL_ON_FAILURE(status); g_calloutsRegistered = TRUE; } HLPR_BAIL_LABEL: #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- PrvWFPSamplerFwpObjectsAddGlobal() [status: %#x]\n", status); #endif /// DBG return status; } /** @private_function="PrvWFPSamplerDeviceDataPopulate" Purpose: Populate the deviceData with the BFE engineHandle and various injection handles.

Notes:

MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF550061.aspx
*/ _IRQL_requires_(PASSIVE_LEVEL) _IRQL_requires_same_ _Check_return_ _Success_(return == STATUS_SUCCESS) NTSTATUS PrvWFPSamplerDeviceDataPopulate(_Inout_ WFPSAMPLER_DEVICE_DATA* pDeviceData) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> PrvWFPSamplerDeviceDataPopulate()\n"); #endif /// DBG NT_ASSERT(pDeviceData); NTSTATUS status = STATUS_SUCCESS; if(FwpmBfeStateGet() == FWPM_SERVICE_RUNNING) { status = KrnlHlprFwpmSessionCreateEngineHandle(&(pDeviceData->pEngineHandle)); HLPR_BAIL_ON_FAILURE(status); } /// There are injection handles for each of the supported sublayers that allow injection. This /// allows us to do multiple injectors in the layer provided that the callouts are in different /// sublayers. for(UINT32 index = 0; index < MAX_INDEX; index++) { #pragma warning(push) #pragma warning(disable: 6388) /// all injection Handles will be 0 initially status = KrnlHlprInjectionHandleDataCreate(&(pDeviceData->ppIPv4InboundInjectionHandles[index]), AF_INET, FWP_DIRECTION_INBOUND, index); HLPR_BAIL_ON_FAILURE(status); status = KrnlHlprInjectionHandleDataCreate(&(pDeviceData->ppIPv4OutboundInjectionHandles[index]), AF_INET, FWP_DIRECTION_OUTBOUND, index); HLPR_BAIL_ON_FAILURE(status); status = KrnlHlprInjectionHandleDataCreate(&(pDeviceData->ppIPv6InboundInjectionHandles[index]), AF_INET6, FWP_DIRECTION_INBOUND, index); HLPR_BAIL_ON_FAILURE(status); status = KrnlHlprInjectionHandleDataCreate(&(pDeviceData->ppIPv6OutboundInjectionHandles[index]), AF_INET6, FWP_DIRECTION_OUTBOUND, index); HLPR_BAIL_ON_FAILURE(status); status = KrnlHlprInjectionHandleDataCreate(&(pDeviceData->ppInboundInjectionHandles[index]), AF_UNSPEC, FWP_DIRECTION_INBOUND, index); HLPR_BAIL_ON_FAILURE(status); status = KrnlHlprInjectionHandleDataCreate(&(pDeviceData->ppOutboundInjectionHandles[index]), AF_UNSPEC, FWP_DIRECTION_OUTBOUND, index); HLPR_BAIL_ON_FAILURE(status); #if(NTDDI_VERSION >= NTDDI_WIN8) pDeviceData->ppRedirectionHandles[index] = &g_pRedirectionHandles[index]; status = KrnlHlprFwpsRedirectHandleCreate(pDeviceData->ppRedirectionHandles[index]); HLPR_BAIL_ON_FAILURE(status); #endif /// (NTDDI_VERSION >= NTDDI_WIN8) #pragma warning(pop) } HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) { for(UINT32 index = 0; index < MAX_INDEX; index++) { #if(NTDDI_VERSION >= NTDDI_WIN8) if(pDeviceData->ppRedirectionHandles[index]) KrnlHlprFwpsRedirectHandleDestroy(pDeviceData->ppRedirectionHandles[index]); #endif /// (NTDDI_VERSION >= NTDDI_WIN8) if(pDeviceData->ppOutboundInjectionHandles[index]) KrnlHlprInjectionHandleDataDestroy(&(pDeviceData->ppOutboundInjectionHandles[index])); if(pDeviceData->ppInboundInjectionHandles[index]) KrnlHlprInjectionHandleDataDestroy(&(pDeviceData->ppInboundInjectionHandles[index])); if(pDeviceData->ppIPv6OutboundInjectionHandles[index]) KrnlHlprInjectionHandleDataDestroy(&(pDeviceData->ppIPv6OutboundInjectionHandles[index])); if(pDeviceData->ppIPv6InboundInjectionHandles[index]) KrnlHlprInjectionHandleDataDestroy(&(pDeviceData->ppIPv6InboundInjectionHandles[index])); if(pDeviceData->ppIPv4OutboundInjectionHandles[index]) KrnlHlprInjectionHandleDataDestroy(&(pDeviceData->ppIPv4OutboundInjectionHandles[index])); if(pDeviceData->ppIPv4InboundInjectionHandles[index]) KrnlHlprInjectionHandleDataDestroy(&(pDeviceData->ppIPv4InboundInjectionHandles[index])); } if(pDeviceData->pEngineHandle && *(pDeviceData->pEngineHandle)) KrnlHlprFwpmSessionReleaseHandle(pDeviceData->pEngineHandle); } #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- PrvWFPSamplerDeviceDataPopulate()\n"); #endif /// DBG return status; } /** @private_function="PrvDriverDeviceAdd" Purpose: Add the device and configure initial WFP callout driver settings.

Notes:

MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF545841.aspx
HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF546090.aspx
HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF545926.aspx
HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF546942.aspx
HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF545854.aspx
HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF546050.aspx
*/ _IRQL_requires_(PASSIVE_LEVEL) _IRQL_requires_same_ _Check_return_ _Success_(return == STATUS_SUCCESS) NTSTATUS PrvDriverDeviceAdd(_In_ WDFDRIVER* pWDFDriver) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> PrvDriverDeviceAdd()\n"); #endif /// DBG NT_ASSERT(pWDFDriver); NTSTATUS status = STATUS_SUCCESS; PWDFDEVICE_INIT pWDFDeviceInit = 0; WDF_OBJECT_ATTRIBUTES attributes = {0}; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.EvtCleanupCallback = EventCleanupDeviceObject; pWDFDeviceInit = WdfControlDeviceInitAllocate(*pWDFDriver, &SDDL_DEVOBJ_KERNEL_ONLY); if(pWDFDeviceInit == 0) { status = STATUS_UNSUCCESSFUL; DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! PrvDriverDeviceAdd : WdfControlDeviceInitAllocate() [status: %#x]\n", status); HLPR_BAIL; } WdfDeviceInitSetDeviceType(pWDFDeviceInit, FILE_DEVICE_NETWORK); status = WdfDeviceCreate(&pWDFDeviceInit, &attributes, &g_WDFDevice); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! PrvDriverDeviceAdd : WdfDeviceCreate() [status: %#x]\n", status); HLPR_BAIL; } g_pWDMDevice = WdfDeviceWdmGetDeviceObject(g_WDFDevice); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(g_pWDMDevice, status); g_pPowerStateEnterIOWorkItem = IoAllocateWorkItem(g_pWDMDevice); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(g_pPowerStateEnterIOWorkItem, status); g_pPowerStateExitIOWorkItem = IoAllocateWorkItem(g_pWDMDevice); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(g_pPowerStateExitIOWorkItem, status); status = RegisterPowerStateChangeCallback(&g_deviceExtension); HLPR_BAIL_ON_FAILURE(status); #pragma warning(push) #pragma warning(disable: 6388) /// g_pNDISPoolData will be 0 status = KrnlHlprNDISPoolDataCreate(&g_pNDISPoolData); HLPR_BAIL_ON_FAILURE(status); #pragma warning(pop) PrvFwpmBfeStateSubscribeChanges(); status = PrvWFPSamplerDeviceDataPopulate(&g_WFPSamplerDeviceData); HLPR_BAIL_ON_FAILURE(status); KeInitializeSpinLock(&g_bpeSpinLock); status = PrvBasicStreamInjectionSerializationListInitialization(); HLPR_BAIL_ON_FAILURE(status); status = PrvWFPSamplerFwpObjectsAddGlobal(&g_WFPSamplerDeviceData); HLPR_BAIL_ON_FAILURE(status); WdfControlFinishInitializing(g_WDFDevice); HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) { if(pWDFDeviceInit) WdfDeviceInitFree(pWDFDeviceInit); } #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- PrvDriverDeviceAdd() [status: %#x]\n", status); #endif /// DBG return status; } /** @framework_function="DriverEntry" Purpose: Entry point for the driver.

Notes:

MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF540807.aspx
HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF547175.aspx
*/ _IRQL_requires_same_ _Function_class_(DRIVER_INITIALIZE) NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT pDriverObject, _In_ PUNICODE_STRING pRegistryPath) { WPP_INIT_TRACING(pDriverObject, pRegistryPath); #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> DriverEntry()\n"); #endif /// DBG NT_ASSERT(pDriverObject); NT_ASSERT(pRegistryPath); NTSTATUS status = STATUS_SUCCESS; WDF_DRIVER_CONFIG driverConfig; WDF_OBJECT_ATTRIBUTES attributes; WDF_DRIVER_CONFIG_INIT(&driverConfig, WDF_NO_EVENT_CALLBACK); ExInitializeDriverRuntime(DrvRtPoolNxOptIn); driverConfig.DriverInitFlags |= WdfDriverInitNonPnpDriver; driverConfig.EvtDriverUnload = EventDriverUnload; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.EvtCleanupCallback = EventCleanupDriverObject; status = WdfDriverCreate(pDriverObject, pRegistryPath, &attributes, &driverConfig, &g_WDFDriver); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! DriverEntry : WdfDriverCreate() [status: %#x]\n", status); HLPR_BAIL; } status = PrvDriverDeviceAdd(&g_WDFDriver); HLPR_BAIL_ON_FAILURE(status); HLPR_BAIL_LABEL: #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- DriverEntry() [status: %#x]\n", status); #endif /// DBG if(status != STATUS_SUCCESS) WPP_CLEANUP(pDriverObject); return status; }