UINT32 PrvScenarioAppContainerEnumExisting()
{
   UINT32                       status           = NO_ERROR;
   UINT32                       numAppContainers = 0;
   INET_FIREWALL_APP_CONTAINER* pAppContainers   = 0;

   status = NetworkIsolationEnumAppContainers(NETISO_FLAG_FORCE_COMPUTE_BINARIES,
                                              (DWORD*)&numAppContainers,
                                              &pAppContainers);

   HLPR_BAIL_ON_FAILURE(status);

   for(UINT32 containerIndex = 0;
       containerIndex < numAppContainers;
       containerIndex++)
   {
      status = PrvScenarioAppContainerAddFwpmObjects(pAppContainers[containerIndex].appContainerSid,
                                                     pAppContainers[containerIndex].userSid,
                                                     pAppContainers[containerIndex].displayName);
      HLPR_BAIL_ON_FAILURE(status);
   }

   HLPR_BAIL_LABEL:

   return status;
}
UINT32 ScenarioAppContainerAdd(_In_ BOOLEAN trustWSH,
                               _In_ BOOLEAN persistent,
                               _In_ BOOLEAN bootTime)
{
   UINT32 status = NO_ERROR;

   if(trustWSH)
      status = PrvScenarioAppContainerAddFwpmObjects(persistent,
                                                     bootTime);
   else
   {
      status = PrvScenarioAppContainerRegister();
      HLPR_BAIL_ON_FAILURE(status);

      status = PrvScenarioAppContainerEnumExisting();
      HLPR_BAIL_ON_FAILURE(status);
   }

   HLPR_BAIL_LABEL:

   if(status == NO_ERROR)
      scenarioConfigured = TRUE;

   return status;
}
VOID PowerStateCallback(_In_ VOID* pCallbackContext,
                        _In_ VOID* pPowerStateEvent,
                        _In_ VOID* pEventSpecifics)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> PowerStateCallback()\n");

#endif /// DBG
   
   UNREFERENCED_PARAMETER(pCallbackContext);

   if(pPowerStateEvent == (VOID*)PO_CB_SYSTEM_STATE_LOCK)
   {
      NTSTATUS status = STATUS_SUCCESS;

      if(pEventSpecifics)
      {
         /// entering the ON state (S0), so return operation to normal
         if(g_calloutsRegistered == FALSE)
         {
            status = KrnlHlprExposedCalloutsRegister();
            HLPR_BAIL_ON_FAILURE(status);

            g_calloutsRegistered = TRUE;
         }
      }
      else
      {
         /// leaving the ON state (S0) to sleep (S1/S2/S3) or hibernate (S4)
         /// Unregister the callouts so no more injection will take place.  By default, the filters 
         /// invoking the callouts will return block.
         if(g_calloutsRegistered == TRUE)
         {
            status = KrnlHlprExposedCalloutsUnregister();
            HLPR_BAIL_ON_FAILURE(status);

            g_calloutsRegistered = FALSE;
         }
      }
   }

   HLPR_BAIL_LABEL:

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- PowerStateCallback()\n");

#endif /// DBG
   
   return;
}
NTSTATUS KrnlHlprThreadedDPCQueue(_In_ KDEFERRED_ROUTINE* pDPCFn,
                                  _In_ CLASSIFY_DATA* pClassifyData,
                                  _In_opt_ INJECTION_DATA* pInjectionData, /* 0 */
                                  _In_opt_ VOID* pContext)                 /* 0 */
{
#if DBG

   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> KrnlHlprThreadedDPCQueue()\n");

#endif /// DBG

   NT_ASSERT(pDPCFn);
   NT_ASSERT(pClassifyData);

   NTSTATUS  status   = STATUS_SUCCESS;
   DPC_DATA* pDPCData = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pDPCData will be freed by caller

   status = KrnlHlprDPCDataCreate(&pDPCData,
                                  pClassifyData,
                                  pInjectionData,
                                  pContext);
   HLPR_BAIL_ON_FAILURE(status);

#pragma warning(pop)

   KeInitializeThreadedDpc(&(pDPCData->kdpc),
                           pDPCFn,
                           0);

   KeInsertQueueDpc(&(pDPCData->kdpc),
                    pDPCData,
                    0);

   HLPR_BAIL_LABEL:

#pragma warning(push)
#pragma warning(disable: 6001) /// pDPCData initialized with call to KrnlHlprDPCDataCreate 

   if(status != STATUS_SUCCESS &&
      pDPCData)
      KrnlHlprDPCDataDestroy(&pDPCData);

#pragma warning(pop)

#if DBG

   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- KrnlHlprThreadedDPCQueue() [status: %#x]\n",
              status);

#endif /// DBG

   return status;
}
_IRQL_requires_same_
VOID SubscriptionBFEStateChangeCallback(_Inout_ VOID* pContext,
                                        _In_ FWPM_SERVICE_STATE bfeState)
{
#if DBG

   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> SubscriptionBFEStateChangeCallback()\n");

#endif /// DBG
   
   NT_ASSERT(pContext);

   NTSTATUS                status      = STATUS_SUCCESS;
   WFPSAMPLER_DEVICE_DATA* pDeviceData = (WFPSAMPLER_DEVICE_DATA*)pContext;

   switch(bfeState)
   {
      case FWPM_SERVICE_RUNNING:
      {
         if(pDeviceData->pEngineHandle == 0)
         {
            status = KrnlHlprFwpmSessionCreateEngineHandle(&(pDeviceData->pEngineHandle));
            HLPR_BAIL_ON_FAILURE(status);
         }

         break;
      }
      case FWPM_SERVICE_STOP_PENDING:
      {
         KrnlHlprFwpmSessionDestroyEngineHandle(&(pDeviceData->pEngineHandle));

         break;
      }
   }

   HLPR_BAIL_LABEL:

#if DBG

      DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                 DPFLTR_INFO_LEVEL,
                 " <--- SubscriptionBFEStateChangeCallback() [status: %#x]\n",
                 status);

#endif /// DBG

   return;
}
DWORD WindowsFirewallNotifyThreadStartRoutine(_In_ LPVOID lpThreadParameter)
{
    ASSERT(lpThreadParameter);

    UINT32         status      = NO_ERROR;
    THREAD_DATA*   pThreadData = (THREAD_DATA*)lpThreadParameter;
    SERVICE_NOTIFY svcNotify   = {0};

    HlprEventSet(pThreadData->threadStartEvent);

    svcNotify.dwVersion         = SERVICE_NOTIFY_STATUS_CHANGE;
    svcNotify.pfnNotifyCallback = WindowsFirewallNotification;
    svcNotify.pContext          = pWFNotifyThread;

    status = HlprServiceNotificationStateChangeRegister(L"MPSSvc",
             &svcNotify,
             SERVICE_NOTIFY_RUNNING,
             &scmHandle,
             &mpsSvcHandle);
    HLPR_BAIL_ON_FAILURE(status);

    status = WaitForSingleObjectEx(mpsSvcHandle,
                                   INFINITE,
                                   TRUE);
    if(status != WAIT_IO_COMPLETION)
    {
        if(status == WAIT_FAILED)
            status = GetLastError();

        HlprLogError(L"WindowsFirewallNotifyThreadStartRoutine : WaitForSingleObjectEx() [status: %#x]",
                     status);
    }

HLPR_BAIL_LABEL:

    HLPR_CLOSE_SERVICE_HANDLE(mpsSvcHandle);

    HLPR_CLOSE_SERVICE_HANDLE(scmHandle);

    return status;
}
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;
}
Exemple #8
0
UINT32 PrvScenarioProxyDeleteFwpmObjects(_In_ const FWPM_FILTER* pFilter)
{
   ASSERT(pFilter);

   UINT32                              status                      = NO_ERROR;
   HANDLE                              engineHandle                = 0;
   HANDLE                              enumHandle                  = 0;
   UINT32                              entryCount                  = 0;
   FWPM_FILTER**                       ppFilters                   = 0;
   FWPM_FILTER_ENUM_TEMPLATE           filterEnumTemplate          = {0};
   FWPM_PROVIDER_CONTEXT_ENUM_TEMPLATE providerContextEnumTemplate = {0};
   GUID                                calloutKey                  = {0};

#if(NTDDI_VERSION >= NTDDI_WIN7)

   if(pFilter->layerKey == FWPM_LAYER_ALE_CONNECT_REDIRECT_V4 ||
      pFilter->layerKey == FWPM_LAYER_ALE_CONNECT_REDIRECT_V6 ||
      pFilter->layerKey == FWPM_LAYER_ALE_BIND_REDIRECT_V4 ||
      pFilter->layerKey == FWPM_LAYER_ALE_BIND_REDIRECT_V6)
      calloutKey = WFPSAMPLER_CALLOUT_PROXY_BY_ALE_REDIRECT;
   else

#endif /// (NTDDI_VERSION >= NTDDI_WIN7)

   calloutKey          = WFPSAMPLER_CALLOUT_PROXY_BY_INJECTION;
   calloutKey.Data4[7] = HlprFwpmLayerGetIDByKey(&(pFilter->layerKey));                          /// Uniquely identifies the callout used

   providerContextEnumTemplate.providerContextType = FWPM_GENERAL_CONTEXT;

   filterEnumTemplate.providerKey             = (GUID*)&WFPSAMPLER_PROVIDER;
   filterEnumTemplate.layerKey                = pFilter->layerKey;
   filterEnumTemplate.enumType                = FWP_FILTER_ENUM_FULLY_CONTAINED;
   filterEnumTemplate.flags                   = FWP_FILTER_ENUM_FLAG_INCLUDE_BOOTTIME |
                                                FWP_FILTER_ENUM_FLAG_INCLUDE_DISABLED;
   filterEnumTemplate.numFilterConditions     = pFilter->numFilterConditions;
   filterEnumTemplate.filterCondition         = pFilter->filterCondition;
   filterEnumTemplate.providerContextTemplate = &providerContextEnumTemplate;
   filterEnumTemplate.actionMask              = FWP_ACTION_FLAG_CALLOUT;
   filterEnumTemplate.calloutKey              = &calloutKey;

   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmFilterCreateEnumHandle(engineHandle,
                                           &filterEnumTemplate,
                                           &enumHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmFilterEnum(engineHandle,
                               enumHandle,
                               0xFFFFFFFF,
                               &ppFilters,
                               &entryCount);
   HLPR_BAIL_ON_FAILURE(status);

   if(ppFilters)
   {
      for(UINT32 filterIndex = 0;
          filterIndex < entryCount;
          filterIndex++)
      {
         HlprFwpmFilterDeleteByKey(engineHandle,
                                   &(ppFilters[filterIndex]->filterKey));

         HlprFwpmCalloutDeleteByKey(engineHandle,
                                    &(ppFilters[filterIndex]->action.calloutKey));

         if(ppFilters[filterIndex]->flags & FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT)
            HlprFwpmProviderContextDeleteByKey(engineHandle,
                                               &(ppFilters[filterIndex]->providerContextKey));
      }

      FwpmFreeMemory((void**)&ppFilters);
   }

   HLPR_BAIL_LABEL:

   if(engineHandle)
   {
      if(enumHandle)
         HlprFwpmFilterDestroyEnumHandle(engineHandle,
                                         &enumHandle);

      HlprFwpmEngineClose(&engineHandle);
   }

   return status;
}
Exemple #9
0
UINT32 PrvScenarioProxyAddFwpmObjects(_In_ const FWPM_FILTER* pFilter,
                                      _In_ const PC_PROXY_DATA* pPCProxyData)
{
   ASSERT(pFilter);
   ASSERT(pPCProxyData);

   UINT32                status          = NO_ERROR;
   HANDLE                engineHandle    = 0;
   FWP_BYTE_BLOB         byteBlob        = {0};
   FWPM_PROVIDER_CONTEXT providerContext = {0};
   FWPM_CALLOUT          callout         = {0};
   FWPM_FILTER           filter          = {0};

   RtlCopyMemory(&filter,
                 pFilter,
                 sizeof(FWPM_FILTER));

   status = HlprGUIDPopulate(&(providerContext.providerContextKey));
   HLPR_BAIL_ON_FAILURE(status);

   providerContext.displayData.name        = L"WFPSampler's Proxy ProviderContext";
   providerContext.displayData.description = L"Instructs the driver where to proxy the socket or connection";      
   providerContext.providerKey             = (GUID*)&WFPSAMPLER_PROVIDER;
   providerContext.type                    = FWPM_GENERAL_CONTEXT;
   providerContext.dataBuffer              = &byteBlob;
   providerContext.dataBuffer->size        = sizeof(PC_PROXY_DATA);
   providerContext.dataBuffer->data        = (UINT8*)pPCProxyData;

#if(NTDDI_VERSION >= NTDDI_WIN7)

   if(pFilter->layerKey == FWPM_LAYER_ALE_CONNECT_REDIRECT_V4 ||
      pFilter->layerKey == FWPM_LAYER_ALE_CONNECT_REDIRECT_V6 ||
      pFilter->layerKey == FWPM_LAYER_ALE_BIND_REDIRECT_V4 ||
      pFilter->layerKey == FWPM_LAYER_ALE_BIND_REDIRECT_V6)
      callout.calloutKey = WFPSAMPLER_CALLOUT_PROXY_BY_ALE_REDIRECT;
   else

#endif /// (NTDDI_VERSION >= NTDDI_WIN7)

   callout.calloutKey              = WFPSAMPLER_CALLOUT_PROXY_BY_INJECTION;
   callout.calloutKey.Data4[7]     = HlprFwpmLayerGetIDByKey(&(filter.layerKey));                /// Uniquely identifies the callout used
   callout.displayData.name        = L"WFPSampler's Proxy Callout";
   callout.displayData.description = L"Proxies the socket or connection to the designated destination";
   callout.flags                   = FWPM_CALLOUT_FLAG_USES_PROVIDER_CONTEXT;
   callout.providerKey             = (GUID*)&WFPSAMPLER_PROVIDER;
   callout.applicableLayer         = filter.layerKey;

   status = HlprGUIDPopulate(&(filter.filterKey));
   HLPR_BAIL_ON_FAILURE(status);

   filter.flags             |= FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT;
   filter.providerKey        = (GUID*)&WFPSAMPLER_PROVIDER;
   filter.subLayerKey        = WFPSAMPLER_SUBLAYER;
   filter.weight.type        = FWP_UINT8;
   filter.weight.uint8       = 0xF;
   filter.action.type        = FWP_ACTION_CALLOUT_UNKNOWN;
   filter.action.calloutKey  = callout.calloutKey;
   filter.providerContextKey = providerContext.providerContextKey;

   if(filter.flags & FWPM_FILTER_FLAG_BOOTTIME ||
      filter.flags & FWPM_FILTER_FLAG_PERSISTENT)
   {
      providerContext.flags |= FWPM_PROVIDER_CONTEXT_FLAG_PERSISTENT;

      callout.flags |= FWPM_CALLOUT_FLAG_PERSISTENT;
   }

   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmTransactionBegin(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmProviderContextAdd(engineHandle,
                                       &providerContext);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmCalloutAdd(engineHandle,
                               &callout);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmFilterAdd(engineHandle,
                              &filter);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmTransactionCommit(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   HLPR_BAIL_LABEL:

   if(engineHandle)
   {
      if(status != NO_ERROR)
         HlprFwpmTransactionAbort(engineHandle);

      HlprFwpmEngineClose(&engineHandle);
   }

   return status;
}
UINT32 PrvScenarioFastStreamInjectionDeleteFwpmObjects(_In_ const FWPM_FILTER* pFilter)
{
   ASSERT(pFilter);

   UINT32                    status             = NO_ERROR;
   HANDLE                    engineHandle       = 0;
   HANDLE                    enumHandle         = 0;
   UINT32                    entryCount         = 0;
   FWPM_FILTER**             ppFilters          = 0;
   FWPM_FILTER_ENUM_TEMPLATE filterEnumTemplate = {0};
   GUID                      calloutKey         = {0};

   calloutKey          = WFPSAMPLER_CALLOUT_FAST_STREAM_INJECTION;
   calloutKey.Data4[7] = HlprFwpmLayerGetIDByKey(&(pFilter->layerKey));                          /// Uniquely identifies the callout used

   filterEnumTemplate.providerKey         = (GUID*)&WFPSAMPLER_PROVIDER;
   filterEnumTemplate.layerKey            = pFilter->layerKey;
   filterEnumTemplate.enumType            = FWP_FILTER_ENUM_FULLY_CONTAINED;
   filterEnumTemplate.flags               = FWP_FILTER_ENUM_FLAG_INCLUDE_BOOTTIME |
                                            FWP_FILTER_ENUM_FLAG_INCLUDE_DISABLED;
   filterEnumTemplate.numFilterConditions = pFilter->numFilterConditions;
   filterEnumTemplate.filterCondition     = pFilter->filterCondition;
   filterEnumTemplate.actionMask          = FWP_ACTION_FLAG_CALLOUT;
   filterEnumTemplate.calloutKey          = &calloutKey;

   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmFilterCreateEnumHandle(engineHandle,
                                           &filterEnumTemplate,
                                           &enumHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmFilterEnum(engineHandle,
                               enumHandle,
                               0xFFFFFFFF,
                               &ppFilters,
                               &entryCount);
   HLPR_BAIL_ON_FAILURE(status);

   if(ppFilters)
   {
      for(UINT32 filterIndex = 0;
          filterIndex < entryCount;
          filterIndex++)
      {
         HlprFwpmFilterDeleteByKey(engineHandle,
                                   &(ppFilters[filterIndex]->filterKey));

         HlprFwpmCalloutDeleteByKey(engineHandle,
                                    &(ppFilters[filterIndex]->action.calloutKey));
      }

      FwpmFreeMemory((void**)&ppFilters);
   }

   HLPR_BAIL_LABEL:

   if(engineHandle)
   {
      if(enumHandle)
         HlprFwpmFilterDestroyEnumHandle(engineHandle,
                                         &enumHandle);

      HlprFwpmEngineClose(&engineHandle);
   }

   return status;
}
UINT32 PrvScenarioFastStreamInjectionAddFwpmObjects(_In_ const FWPM_FILTER* pFilter)
{
   ASSERT(pFilter);

   UINT32       status       = NO_ERROR;
   HANDLE       engineHandle = 0;
   FWPM_CALLOUT callout      = {0};
   FWPM_FILTER  filter       = {0};

   RtlCopyMemory(&filter,
                 pFilter,
                 sizeof(FWPM_FILTER));

   callout.calloutKey              = WFPSAMPLER_CALLOUT_FAST_STREAM_INJECTION;
   callout.calloutKey.Data4[7]     = HlprFwpmLayerGetIDByKey(&(filter.layerKey));                /// Uniquely identifies the callout used
   callout.displayData.name        = L"WFPSampler's Fast Stream Injection Callout";
   callout.displayData.description = L"Causes callout invocation which blindly injects data back into the stream";
   callout.providerKey             = (GUID*)&WFPSAMPLER_PROVIDER;
   callout.applicableLayer         = filter.layerKey;

   status = HlprGUIDPopulate(&(filter.filterKey));
   HLPR_BAIL_ON_FAILURE(status);

   filter.providerKey        = (GUID*)&WFPSAMPLER_PROVIDER;
   filter.subLayerKey        = WFPSAMPLER_SUBLAYER;
   filter.weight.type        = FWP_UINT8;
   filter.weight.uint8       = 0xF;
   filter.action.type        = FWP_ACTION_CALLOUT_TERMINATING;
   filter.action.calloutKey  = callout.calloutKey;

   if(filter.flags & FWPM_FILTER_FLAG_BOOTTIME ||
      filter.flags & FWPM_FILTER_FLAG_PERSISTENT)
      callout.flags = FWPM_CALLOUT_FLAG_PERSISTENT;
 
   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmTransactionBegin(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmCalloutAdd(engineHandle,
                               &callout);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmFilterAdd(engineHandle,
                              &filter);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmTransactionCommit(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   HLPR_BAIL_LABEL:

   if(engineHandle)
   {
      if(status != NO_ERROR)
         HlprFwpmTransactionAbort(engineHandle);

      HlprFwpmEngineClose(&engineHandle);
   }

   return status;
}
NTSTATUS KrnlHlprWorkItemQueue(_In_ PDEVICE_OBJECT pWDMDevice,
                               _In_ IO_WORKITEM_ROUTINE* pWorkItemFn,
                               _In_ CLASSIFY_DATA* pClassifyData,
                               _In_ REDIRECT_DATA* pRedirectData,
                               _In_opt_ VOID* pContext)               /* 0 */
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> KrnlHlprWorkItemQueue()\n");

#endif /// DBG
   
   NT_ASSERT(pWDMDevice);
   NT_ASSERT(pWorkItemFn);
   NT_ASSERT(pClassifyData);
   NT_ASSERT(pRedirectData);

   NTSTATUS       status        = STATUS_SUCCESS;
   PIO_WORKITEM   pIOWorkItem   = 0;
   WORKITEM_DATA* pWorkItemData = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pIOWorkItem is cleaned up in KrnlHlprWorkItemDataDestroy

   pIOWorkItem = IoAllocateWorkItem(pWDMDevice);
   if(pIOWorkItem == 0)
   {
      status = STATUS_UNSUCCESSFUL;

      DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                 DPFLTR_ERROR_LEVEL,
                 " !!!! KrnlHlprWorkItemQueue : IoAllocateWorkItem() [status: %#x]\n",
                 status);

      HLPR_BAIL;
   }

#pragma warning(pop)

   status = KrnlHlprWorkItemDataCreate(&pWorkItemData,
                                       pClassifyData,
                                       pRedirectData,
                                       pIOWorkItem,
                                       pContext);
   HLPR_BAIL_ON_FAILURE(status);

   IoQueueWorkItem(pWorkItemData->pIOWorkItem,
                   pWorkItemFn,
                   DelayedWorkQueue,
                   (PVOID)pWorkItemData);

   HLPR_BAIL_LABEL:

   if(status != STATUS_SUCCESS &&
      pWorkItemData)
      KrnlHlprWorkItemDataDestroy(&pWorkItemData);

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- KrnlHlprWorkItemQueue() [status: %#x]\n",
              status);

#endif /// DBG
   
   return status;
}
_IRQL_requires_same_
VOID ClassifyPendAuthorization(_In_ const FWPS_INCOMING_VALUES* pClassifyValues,
                               _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata,
                               _Inout_opt_ VOID* pNetBufferList,
                               _In_ const FWPS_FILTER* pFilter,
                               _In_ UINT64 flowContext,
                               _Inout_ FWPS_CLASSIFY_OUT* pClassifyOut)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> ClassifyPendAuthorization()\n");

#endif /// DBG
   
   NT_ASSERT(pClassifyValues);
   NT_ASSERT(pMetadata);
   NT_ASSERT(pFilter);
   NT_ASSERT(pClassifyOut);
   NT_ASSERT(pClassifyValues->layerId == FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_LISTEN_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_LISTEN_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_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_AUTHORIZATION_DATA));
   NT_ASSERT(pFilter->providerContext->dataBuffer->data);

   NTSTATUS                    status                 = STATUS_SUCCESS;
   PC_PEND_AUTHORIZATION_DATA* pPendAuthorizationData = (PC_PEND_AUTHORIZATION_DATA*)pFilter->providerContext->dataBuffer->data;

   /// RESOURCE_ASSIGNTMENT & AUTH_LISTEN will Reauthorize after the completion of the pend.
   /// AUTH_CONNECT's completeOperation will trigger a Reauthorization
   if(KrnlHlprFwpsIncomingValueConditionFlagsAreSet(pClassifyValues,
                                                    FWP_CONDITION_FLAG_IS_REAUTHORIZE))
   {
      if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
         pClassifyOut->actionType = pPendAuthorizationData->finalAction;
   }
   else
   {
      BOOLEAN actionSet = FALSE;

      if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
      {
         INJECTION_DATA* pInjectionData = 0;
         PEND_DATA*      pPendData      = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

         if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6)
         {
            status = KrnlHlprInjectionDataCreate(&pInjectionData,
                                                 pClassifyValues,
                                                 pMetadata,
                                                 (NET_BUFFER_LIST*)pNetBufferList);
            HLPR_BAIL_ON_FAILURE(status);
         }

#pragma warning(pop)

         /// AUTH_RECV_ACCEPT's injection will be indicative of PERMIT
         if(pInjectionData &&
            pInjectionData->injectionState == FWPS_PACKET_INJECTED_BY_SELF)
         {
            pClassifyOut->actionType = pPendAuthorizationData->finalAction;

            actionSet = TRUE;
         }
         else
         {
#pragma warning(push)
#pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

            status = KrnlHlprPendDataCreate(&pPendData,
                                            pMetadata,
                                            (NET_BUFFER_LIST*)pNetBufferList,
                                            pFilter);
            HLPR_BAIL_ON_FAILURE(status);

#pragma warning(pop)

            status = TriggerPendAuthorizationOutOfBand(pClassifyValues,
                                                       pMetadata,
                                                       pNetBufferList,
                                                       0,
                                                       pFilter,
                                                       flowContext,
                                                       pClassifyOut,
                                                       pInjectionData,
                                                       pPendData,
                                                       pPendAuthorizationData);
         }

         HLPR_BAIL_LABEL:

         if(status != STATUS_SUCCESS)
         {
            DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                       DPFLTR_ERROR_LEVEL,
                       " !!!! ClassifyPendAuthorization() [status: %#x]\n",
                       status);

            if(pInjectionData)
               KrnlHlprInjectionDataDestroy(&pInjectionData);

            if(pPendData)
               KrnlHlprPendDataDestroy(&pPendData);
         }

         if(!actionSet)
         {
            pClassifyOut->actionType  = FWP_ACTION_BLOCK;
            pClassifyOut->flags      |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
         }
      }
   }

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- ClassifyPendAuthorization()\n");

#endif /// DBG
   
   return;
}
NTSTATUS TriggerPendAuthorizationOutOfBand(_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,
                                           _In_ FWPS_CLASSIFY_OUT* pClassifyOut,
                                           _Inout_opt_ INJECTION_DATA* pInjectionData,
                                           _Inout_ PEND_DATA* pPendData,
                                           _In_ PC_PEND_AUTHORIZATION_DATA* pPCData)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> TriggerPendAuthorizationOutOfBand()\n");

#endif /// DBG
   
   NT_ASSERT(pClassifyValues);
   NT_ASSERT(pMetadata);
   NT_ASSERT(pFilter);
   NT_ASSERT(pClassifyOut);
   NT_ASSERT(pPendData);
   NT_ASSERT(pPCData);
 
   NTSTATUS       status        = STATUS_SUCCESS;
   CLASSIFY_DATA* pClassifyData = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

   status = KrnlHlprClassifyDataCreateLocalCopy(&pClassifyData,
                                                pClassifyValues,
                                                pMetadata,
                                                pLayerData,
                                                pClassifyContext,
                                                pFilter,
                                                flowContext,
                                                pClassifyOut);
   HLPR_BAIL_ON_FAILURE(status);

#pragma warning(pop)

   if(pPCData->useWorkItems ||
      pPCData->delay)
   {
      /// introducing the delay requires PASSIVE_LEVEL, so force use of a Work Item
      status = KrnlHlprWorkItemQueue(g_pWDMDevice,
                                     PendAuthorizationWorkItemRoutine,
                                     pClassifyData,
                                     pPendData,
                                     (VOID*)pInjectionData);
   }
   else
   {
      if(pPCData->useThreadedDPC)
         status = KrnlHlprThreadedDPCQueue(PendAuthorizationDeferredProcedureCall,
                                           pClassifyData,
                                           pPendData,
                                           pInjectionData);
      else
         status = KrnlHlprDPCQueue(PendAuthorizationDeferredProcedureCall,
                                   pClassifyData,
                                   pPendData,
                                   pInjectionData);
   }

   HLPR_BAIL_ON_FAILURE(status);

   pClassifyOut->actionType = FWP_ACTION_BLOCK;

   HLPR_BAIL_LABEL:

   if(status != STATUS_SUCCESS)
   {
      if(pClassifyData)
         KrnlHlprClassifyDataDestroyLocalCopy(&pClassifyData);
   }

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- TriggerPendAuthorizationOutOfBand() [status: %#x]\n",
              status);

#endif /// DBG
   
   return status;
}
/**
 @framework_function="RPCClientInterfaceInitialize"
 
   Purpose:  Initialize the RPC client interface by creating a fast binding handle.             <br>
                                                                                                <br>
   Notes:                                                                                       <br>
                                                                                                <br>
   MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/AA378651.aspx              <br>
             HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/AA375587.aspx              <br>
             HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/AA375583.aspx              <br>
*/
UINT32 RPCClientInterfaceInitialize()
{
   RPC_STATUS                     status                = RPC_S_OK;
   SID*                           pLocalSystemSID       = 0;
   SIZE_T                         sidSize               = 0;
   RPC_SECURITY_QOS_V4            securityQoS           = {0};
   RPC_BINDING_HANDLE_TEMPLATE_V1 bindingHandleTemplate = {0};
   RPC_BINDING_HANDLE_SECURITY_V1 bindingHandleSecurity = {0};
   RPC_BINDING_HANDLE_OPTIONS_V1  bindingHandleOptions  = {0};

   HLPR_NEW(pRPCData,
            RPC_DATA);
   HLPR_BAIL_ON_ALLOC_FAILURE(pRPCData,
                              status);

   status = HlprSIDCreate(&pLocalSystemSID,
                          &sidSize,
                          0,
                          WinLocalSystemSid);
   HLPR_BAIL_ON_FAILURE(status);

   wfpSamplerBindingHandle = 0;

   pRPCData->rpcClientInterfaceHandle = IWFPSampler_v1_0_c_ifspec;      /// MIDL generated Client Interface Handle
   pRPCData->protocolSequence         = RPC_PROTSEQ_LRPC;               /// Use Local RPC

   securityQoS.Version           = 4;                                   /// Use RPC_SECURITY_QOS_V4 structure
   securityQoS.Capabilities      = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;  /// Request mutual authentication from the security provider
   securityQoS.IdentityTracking  = RPC_C_QOS_IDENTITY_STATIC;           /// Security context is created only once
   securityQoS.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;            /// Allow server to get client's identity and allow it's impersonation
   securityQoS.Sid               = pLocalSystemSID;                     /// Security identifier used by Local RPC
   securityQoS.EffectiveOnly     = TRUE;                                /// only see enabled privileges

   bindingHandleTemplate.Version          = 1;                          /// Use BINDING_HANDLE_TEMPLATE_V1 structure
   bindingHandleTemplate.ProtocolSequence = pRPCData->protocolSequence; /// Use Local RPC
   bindingHandleTemplate.StringEndpoint   = (PWSTR)g_pEndpoint;         /// String representation of our endpoint

   bindingHandleSecurity.Version     = 1;                               /// Use BINDING_HANDLE_SECURITY_V1 structure
   bindingHandleSecurity.AuthnLevel  = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;   /// Authentication level which causes Local RPC to use a secure channel
   bindingHandleSecurity.AuthnSvc    = RPC_C_AUTHN_WINNT;               /// Autherntication service to use
   bindingHandleSecurity.SecurityQos = (RPC_SECURITY_QOS*)&securityQoS; /// Security Qos Settings to Use

   bindingHandleOptions.Version    = 1;                                 /// Use BINDING_HANDLE_OPTIONS_V1 structure
   bindingHandleOptions.Flags      = RPC_BHO_NONCAUSAL;                 /// Execute calls in any order
   bindingHandleOptions.ComTimeout = RPC_C_BINDING_DEFAULT_TIMEOUT;     /// Use default communication timeout value

   status = RpcBindingCreate(&bindingHandleTemplate,                    /// Core structure of the binding handle
                             &bindingHandleSecurity,                    /// Security options for the binding handle
                             &bindingHandleOptions,                     /// Additional options to set on the binding handle
                             &wfpSamplerBindingHandle);                 /// Created binding handle
   if(status != RPC_S_OK)
   {
      HlprLogError(L"RPCClientInterfaceInitialize : RpcBindingCreate() [status: %#x]",
                   status);

      HLPR_BAIL;
   }

   pRPCData->bindingHandle = wfpSamplerBindingHandle;

   status = RpcBindingBind(0,                                           /// These RPC calls will be synchronous
                           pRPCData->bindingHandle,                     /// Binding handle that will be used to make the RPC call
                           pRPCData->rpcClientInterfaceHandle);         /// Interface handle that will be used to make the RPC call
   if(status != RPC_S_OK)
   {
      HlprLogError(L"RPCClientInterfaceInitialize : RpcBindingBind() [status: %#x]",
                   status);

      HLPR_BAIL;
   }

   HLPR_BAIL_LABEL:

   if(status != RPC_S_OK)
   {
      HlprLogError(L"[status: %#x]",
                   status);

      PrvRPCTroubleshootError();

      RPCClientInterfaceTerminate();
   }

   if(pLocalSystemSID)
      HlprSIDDestroy(&pLocalSystemSID);

   return status;
}
UINT32 PrvScenarioAppContainerDeleteFwpmObjects(_In_ const SID* pPackageID,
                                                _In_ const SID* pUserID)
{
   UNREFERENCED_PARAMETER(pUserID);

   ASSERT(pPackageID);
   ASSERT(pUserID);

   UINT32                status                            = NO_ERROR;
///   UINT32                sidSize                           = 0;
   HANDLE                engineHandle                      = 0;
   const GUID            pLayerKeys[]                      = {FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
                                                              FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6,
                                                              FWPM_LAYER_ALE_AUTH_CONNECT_V4,
                                                              FWPM_LAYER_ALE_AUTH_CONNECT_V6};
   const UINT8           NUM_CONDITIONS                    = 1; /// 2
   const UINT8           NUM_OBJECTS                       = RTL_NUMBER_OF(pLayerKeys);
   FWPM_FILTER_CONDITION pFilterConditions[NUM_CONDITIONS] = {0};

   pFilterConditions[0].fieldKey            = FWPM_CONDITION_ALE_PACKAGE_ID;
   pFilterConditions[0].matchType           = FWP_MATCH_EQUAL;
   pFilterConditions[0].conditionValue.type = FWP_SID;
   pFilterConditions[0].conditionValue.sid  = (SID*)pPackageID;

///   pFilterConditions[1].fieldKey            = FWPM_CONDITION_ALE_USER_ID;
///   pFilterConditions[1].matchType           = FWP_MATCH_EQUAL;
///   pFilterConditions[1].conditionValue.type = FWP_SECURITY_DESCRIPTOR_TYPE;
///   pFilterConditions[1].conditionValue.sd   = ;

   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   for(UINT32 objectIndex = 0;
       objectIndex < NUM_OBJECTS;
       objectIndex++)
   {
      UINT32                    entryCount         = 0;
      FWPM_FILTER**             ppFilters          = 0;
      HANDLE                    enumHandle         = 0;
      FWPM_FILTER_ENUM_TEMPLATE filterEnumTemplate = {0};

      filterEnumTemplate.providerKey         = (GUID*)&WFPSAMPLER_PROVIDER;
      filterEnumTemplate.layerKey            = pLayerKeys[objectIndex];
      filterEnumTemplate.enumType            = FWP_FILTER_ENUM_FULLY_CONTAINED;
      filterEnumTemplate.flags               = FWP_FILTER_ENUM_FLAG_INCLUDE_BOOTTIME |
                                               FWP_FILTER_ENUM_FLAG_INCLUDE_DISABLED;
      filterEnumTemplate.numFilterConditions = NUM_CONDITIONS;
      filterEnumTemplate.filterCondition     = pFilterConditions;
      filterEnumTemplate.actionMask          = 0xFFFFFFFF;

      status = HlprFwpmFilterCreateEnumHandle(engineHandle,
                                              &filterEnumTemplate,
                                              &enumHandle);
      HLPR_BAIL_ON_FAILURE_WITH_LABEL(status,
                                      HLPR_BAIL_LABEL_2);

      status = HlprFwpmFilterEnum(engineHandle,
                                  enumHandle,
                                  0xFFFFFFFF,
                                  &ppFilters,
                                  &entryCount);
      HLPR_BAIL_ON_FAILURE_WITH_LABEL(status,
                                      HLPR_BAIL_LABEL_2);

      if(ppFilters)
      {
         for(UINT32 filterIndex = 0;
             filterIndex < entryCount;
             filterIndex++)
         {
            HlprFwpmFilterDeleteByKey(engineHandle,
                                      &(ppFilters[filterIndex]->filterKey));
         }

         FwpmFreeMemory((void**)&ppFilters);
      }

      HLPR_BAIL_LABEL_2:

      if(enumHandle)
         HlprFwpmFilterDestroyEnumHandle(engineHandle,
                                         &enumHandle);
   }

   HLPR_BAIL_LABEL:

   HlprFwpmEngineClose(&engineHandle);

   return status;
}
UINT32 PrvBasicPacketModificationScenarioAddFwpmObjects(_In_ const FWPM_FILTER* pFilter,
                                                        _In_ const PC_BASIC_PACKET_MODIFICATION_DATA* pPCBasicPacketModificationData)
{
   ASSERT(pFilter);
   ASSERT(pPCBasicPacketModificationData);

   UINT32                status          = NO_ERROR;
   HANDLE                engineHandle    = 0;
   FWP_BYTE_BLOB         byteBlob        = {0};
   FWPM_PROVIDER_CONTEXT providerContext = {0};
   FWPM_CALLOUT          callout         = {0};
   FWPM_FILTER           filter          = {0};

   RtlCopyMemory(&filter,
                 pFilter,
                 sizeof(FWPM_FILTER));

   status = HlprGUIDPopulate(&(providerContext.providerContextKey));
   HLPR_BAIL_ON_FAILURE(status);

   providerContext.displayData.name = L"WFPSampler's Basic Packet Modification Provider Context";
   providerContext.providerKey      = (GUID*)&WFPSAMPLER_PROVIDER;
   providerContext.type             = FWPM_GENERAL_CONTEXT;
   providerContext.dataBuffer       = &byteBlob;
   providerContext.dataBuffer->size = sizeof(PC_BASIC_PACKET_MODIFICATION_DATA);
   providerContext.dataBuffer->data = (UINT8*)pPCBasicPacketModificationData;

   callout.calloutKey              = WFPSAMPLER_CALLOUT_BASIC_PACKET_MODIFICATION;
   callout.calloutKey.Data4[7]     = HlprFwpmLayerGetIDByKey(&(filter.layerKey));             /// Uniquely identifies the callout used
   callout.displayData.name        = L"WFPSampler's Basic Packet Modification Callout";
   callout.displayData.description = L"Causes callout invocation which modifies the headers and injects traffic back";
   callout.flags                   = FWPM_CALLOUT_FLAG_USES_PROVIDER_CONTEXT;
   callout.providerKey             = (GUID*)&WFPSAMPLER_PROVIDER;
   callout.applicableLayer         = filter.layerKey;

   status = HlprGUIDPopulate(&(filter.filterKey));
   HLPR_BAIL_ON_FAILURE(status);

   filter.flags               |= FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT;
   filter.providerKey          = (GUID*)&WFPSAMPLER_PROVIDER;
   filter.subLayerKey          = WFPSAMPLER_SUBLAYER;
   filter.weight.type          = FWP_UINT8;
   filter.weight.uint8         = 0xF;
   filter.action.type          = FWP_ACTION_CALLOUT_UNKNOWN;
   filter.action.calloutKey    = callout.calloutKey;
   filter.providerContextKey   = providerContext.providerContextKey;

   if(filter.flags & FWPM_FILTER_FLAG_BOOTTIME ||
      filter.flags & FWPM_FILTER_FLAG_PERSISTENT)
   {
      providerContext.flags |= FWPM_PROVIDER_CONTEXT_FLAG_PERSISTENT;

      callout.flags |= FWPM_CALLOUT_FLAG_PERSISTENT;
   }

   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmTransactionBegin(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmProviderContextAdd(engineHandle,
                                       &providerContext);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmCalloutAdd(engineHandle,
                               &callout);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmFilterAdd(engineHandle,
                              &filter);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmTransactionCommit(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   HLPR_BAIL_LABEL:

   if(engineHandle)
   {
      if(status != NO_ERROR)
         HlprFwpmTransactionAbort(engineHandle);

      HlprFwpmEngineClose(&engineHandle);
   }

   return status;
}
UINT32 PrvScenarioAppContainerAddFwpmObjects(_In_ BOOLEAN persistent = TRUE,
                                             _In_ BOOLEAN bootTime = FALSE)
{
   UINT32                status                = NO_ERROR;
   UINT32                sidSize               = 0;
   HANDLE                engineHandle          = 0;
   const GUID            pLayerKeys[]          = {FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
                                                  FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6,
                                                  FWPM_LAYER_ALE_AUTH_CONNECT_V4,
                                                  FWPM_LAYER_ALE_AUTH_CONNECT_V6};
   const UINT32          NUM_OBJECTS           = RTL_NUMBER_OF(pLayerKeys);
   FWPM_FILTER_CONDITION filterCondition       = {0};
   FWPM_FILTER           pFilters[NUM_OBJECTS] = {0};

   /// Only App Containers have a valid (non-NULL) SID for the ALE_PACKAGE_ID
   filterCondition.fieldKey            = FWPM_CONDITION_ALE_PACKAGE_ID;
   filterCondition.matchType           = FWP_MATCH_NOT_EQUAL;
   filterCondition.conditionValue.type = FWP_SID;

#pragma warning(push)
#pragma warning(disable: 6388) /// filterCondition.conditionValue.sid guaranteed to be 0 due to ZeroMemory call

   status = HlprSIDGetWellKnown(WinNullSid,
                                &(filterCondition.conditionValue.sid),
                                &sidSize);
   HLPR_BAIL_ON_FAILURE(status);

#pragma warning(pop)

   for(UINT32 objectIndex = 0;
       objectIndex < NUM_OBJECTS;
       objectIndex++)
   {
      status = HlprGUIDPopulate(&(pFilters[objectIndex].filterKey));
      HLPR_BAIL_ON_FAILURE(status);

      pFilters[objectIndex].displayData.name         = L"WFPSampler's AppContainer Scenario Filter";
      pFilters[objectIndex].displayData.description  = L"Trust Windows Service Hardening to handle all App Containers";
      pFilters[objectIndex].flags                   |= FWPM_FILTER_FLAG_PERSISTENT;
      pFilters[objectIndex].providerKey              = (GUID*)&WFPSAMPLER_PROVIDER;
      pFilters[objectIndex].layerKey                 = pLayerKeys[objectIndex];
      pFilters[objectIndex].subLayerKey              = WFPSAMPLER_SUBLAYER;
      pFilters[objectIndex].weight.type              = FWP_UINT8;
      pFilters[objectIndex].weight.uint8             = 0xF;
      pFilters[objectIndex].numFilterConditions      = 1;
      pFilters[objectIndex].filterCondition          = &filterCondition;
      pFilters[objectIndex].action.type              = FWP_ACTION_PERMIT;

      if(!persistent)
         pFilters[objectIndex].flags ^= FWPM_FILTER_FLAG_PERSISTENT;

      if(bootTime)
      {
         if(pFilters[objectIndex].flags & FWPM_FILTER_FLAG_PERSISTENT)
            pFilters[objectIndex].flags ^= FWPM_FILTER_FLAG_PERSISTENT;

         pFilters[objectIndex].flags |= FWPM_FILTER_FLAG_BOOTTIME;
      }
   }

   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmTransactionBegin(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   for(UINT32 objectIndex = 0;
       objectIndex < NUM_OBJECTS;
       objectIndex++)
   {
      status = HlprFwpmFilterAdd(engineHandle,
                                 &(pFilters[objectIndex]));
      HLPR_BAIL_ON_FAILURE(status);
   }

   status = HlprFwpmTransactionCommit(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   HLPR_BAIL_LABEL:

   HlprSIDDestroy(&(filterCondition.conditionValue.sid));

   if(engineHandle)
   {
      if(status != NO_ERROR)
         HlprFwpmTransactionAbort(engineHandle);

      HlprFwpmEngineClose(&engineHandle);
   }

   return status;
}
UINT32 PrvScenarioAppContainerAddFwpmObjects(_In_ const SID* pPackageID,
                                             _In_ const SID* pUserID,
                                             _In_opt_ PCWSTR pDisplayName,
                                             _In_ BOOLEAN persistent = TRUE,
                                             _In_ BOOLEAN bootTime = FALSE)
{
   UNREFERENCED_PARAMETER(pUserID);

   ASSERT(pPackageID);
   ASSERT(pUserID);

   UINT32                status                            = NO_ERROR;
///   UINT32                sidSize                           = 0;
   HANDLE                engineHandle                      = 0;
   const GUID            pLayerKeys[]                      = {FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
                                                              FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6,
                                                              FWPM_LAYER_ALE_AUTH_CONNECT_V4,
                                                              FWPM_LAYER_ALE_AUTH_CONNECT_V6};
   const UINT8           NUM_CONDITIONS                    = 1; /// 2
   const UINT8           NUM_OBJECTS                       = RTL_NUMBER_OF(pLayerKeys);
   FWPM_FILTER_CONDITION pFilterConditions[NUM_CONDITIONS] = {0};
   FWPM_FILTER           pFilters[NUM_OBJECTS]             = {0};

///   status = HlprSecurityDescriptorGetSelfRelativeForUser();

   pFilterConditions[0].fieldKey            = FWPM_CONDITION_ALE_PACKAGE_ID;
   pFilterConditions[0].matchType           = FWP_MATCH_EQUAL;
   pFilterConditions[0].conditionValue.type = FWP_SID;
   pFilterConditions[0].conditionValue.sid  = (SID*)pPackageID;

///   pFilterConditions[1].fieldKey            = FWPM_CONDITION_ALE_USER_ID;
///   pFilterConditions[1].matchType           = FWP_MATCH_EQUAL;
///   pFilterConditions[1].conditionValue.type = FWP_SECURITY_DESCRIPTOR_TYPE;
///   pFilterConditions[1].conditionValue.sd   = ;

   for(UINT32 objectIndex = 0;
       objectIndex < NUM_OBJECTS;
       objectIndex++)
   {
      status = HlprGUIDPopulate(&(pFilters[objectIndex].filterKey));
      HLPR_BAIL_ON_FAILURE(status);

      pFilters[objectIndex].displayData.name         = L"WFPSampler's AppContainer Scenario Filter";
      pFilters[objectIndex].displayData.description  = (PWSTR)pDisplayName;
      pFilters[objectIndex].flags                   |= FWPM_FILTER_FLAG_PERSISTENT;
      pFilters[objectIndex].providerKey              = (GUID*)&WFPSAMPLER_PROVIDER;
      pFilters[objectIndex].layerKey                 = pLayerKeys[objectIndex];
      pFilters[objectIndex].subLayerKey              = WFPSAMPLER_SUBLAYER;
      pFilters[objectIndex].weight.type              = FWP_UINT8;
      pFilters[objectIndex].weight.uint8             = 0xF;
      pFilters[objectIndex].numFilterConditions      = NUM_CONDITIONS;
      pFilters[objectIndex].filterCondition          = pFilterConditions;
      pFilters[objectIndex].action.type              = FWP_ACTION_PERMIT;

      if(!persistent)
         pFilters[objectIndex].flags ^= FWPM_FILTER_FLAG_PERSISTENT;

      if(bootTime)
      {
         if(pFilters[objectIndex].flags & FWPM_FILTER_FLAG_PERSISTENT)
            pFilters[objectIndex].flags ^= FWPM_FILTER_FLAG_PERSISTENT;

         pFilters[objectIndex].flags |= FWPM_FILTER_FLAG_BOOTTIME;
      }
   }

   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   status = HlprFwpmTransactionBegin(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   for(UINT32 objectIndex = 0;
       objectIndex < NUM_OBJECTS;
       objectIndex++)
   {
      status = HlprFwpmFilterAdd(engineHandle,
                                 &(pFilters[objectIndex]));
      HLPR_BAIL_ON_FAILURE(status);
   }

   status = HlprFwpmTransactionCommit(engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   HLPR_BAIL_LABEL:

   if(engineHandle)
   {
      if(status != NO_ERROR)
         HlprFwpmTransactionAbort(engineHandle);

      HlprFwpmEngineClose(&engineHandle);
   }

   return status;
}
UINT32 PrvScenarioAppContainerDeleteFwpmObjects()
{
   UINT32                status          = NO_ERROR;
   UINT32                sidSize         = 0;
   HANDLE                engineHandle    = 0;
   const GUID            pLayerKeys[]    = {FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
                                            FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6,
                                            FWPM_LAYER_ALE_AUTH_CONNECT_V4,
                                            FWPM_LAYER_ALE_AUTH_CONNECT_V6};
   const UINT32          NUM_OBJECTS     = RTL_NUMBER_OF(pLayerKeys);
   FWPM_FILTER_CONDITION filterCondition = {0};

   /// Only App Containers have a valid (non-NULL) SID for the ALE_PACKAGE_ID
   filterCondition.fieldKey            = FWPM_CONDITION_ALE_PACKAGE_ID;
   filterCondition.matchType           = FWP_MATCH_NOT_EQUAL;
   filterCondition.conditionValue.type = FWP_SID;

#pragma warning(push)
#pragma warning(disable: 6388) /// filterCondition.conditionValue.sid guaranteed to be 0 due to ZeroMemory call

   status = HlprSIDGetWellKnown(WinNullSid,
                                &(filterCondition.conditionValue.sid),
                                &sidSize);
   HLPR_BAIL_ON_FAILURE(status);

#pragma warning(pop)

   status = HlprFwpmEngineOpen(&engineHandle);
   HLPR_BAIL_ON_FAILURE(status);

   for(UINT32 objectIndex = 0;
       objectIndex < NUM_OBJECTS;
       objectIndex++)
   {
      HANDLE                    enumHandle         = 0;
      UINT32                    entryCount         = 0;
      FWPM_FILTER**             ppFilters          = 0;
      FWPM_FILTER_ENUM_TEMPLATE filterEnumTemplate = {0};

      filterEnumTemplate.providerKey         = (GUID*)&WFPSAMPLER_PROVIDER;
      filterEnumTemplate.layerKey            = pLayerKeys[objectIndex];
      filterEnumTemplate.enumType            = FWP_FILTER_ENUM_FULLY_CONTAINED;
      filterEnumTemplate.flags               = FWP_FILTER_ENUM_FLAG_INCLUDE_BOOTTIME |
                                               FWP_FILTER_ENUM_FLAG_INCLUDE_DISABLED;
      filterEnumTemplate.numFilterConditions = 1;
      filterEnumTemplate.filterCondition     = &filterCondition;
      filterEnumTemplate.actionMask          = 0xFFFFFFFF;

      status = HlprFwpmFilterCreateEnumHandle(engineHandle,
                                              &filterEnumTemplate,
                                              &enumHandle);
      HLPR_BAIL_ON_FAILURE_WITH_LABEL(status,
                                      HLPR_BAIL_LABEL_2);

      status = HlprFwpmFilterEnum(engineHandle,
                                  enumHandle,
                                  0xFFFFFFFF,
                                  &ppFilters,
                                  &entryCount);
      HLPR_BAIL_ON_FAILURE_WITH_LABEL(status,
                                      HLPR_BAIL_LABEL_2);

      if(ppFilters)
      {
         for(UINT32 filterIndex = 0;
             filterIndex < entryCount;
             filterIndex++)
         {
            HlprFwpmFilterDeleteByKey(engineHandle,
                                      &(ppFilters[filterIndex]->filterKey));
         }

         FwpmFreeMemory((void**)&ppFilters);
      }

      HLPR_BAIL_LABEL_2:

      if(enumHandle)
         HlprFwpmFilterDestroyEnumHandle(engineHandle,
                                         &enumHandle);
   }

   HLPR_BAIL_LABEL:

   HlprSIDDestroy(&(filterCondition.conditionValue.sid));

   HlprFwpmEngineClose(&engineHandle);

   return status;
}