NTSTATUS KrnlHlprThreadedDPCQueue(_In_ KDEFERRED_ROUTINE* pDPCFn)
{
#if DBG

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

#endif /// DBG

   NT_ASSERT(pDPCFn);

   NTSTATUS  status   = STATUS_SUCCESS;
   DPC_DATA* pDPCData = 0;

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

   HLPR_NEW(pDPCData,
            DPC_DATA,
            WFPSAMPLER_SYSLIB_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(pDPCData,
                              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 HLPR_NEW 

   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;
}
NTSTATUS NotifyPendAuthorizationNotification(_In_ FWPS_CALLOUT_NOTIFY_TYPE notificationType,
                                             _In_ const GUID* pFilterKey,
                                             _Inout_ FWPS_FILTER* pFilter)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> NotifyPendAuthorizationNotification()\n");

#endif /// DBG
   
   NT_ASSERT(pFilter);

   NTSTATUS     status      = STATUS_SUCCESS;
   NOTIFY_DATA* pNotifyData = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pNotifyData is expected to be cleaned up by caller using PrvPendAuthorizationNotificationWorkItemRoutine

   HLPR_NEW(pNotifyData,
            NOTIFY_DATA,
            WFPSAMPLER_CALLOUT_DRIVER_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(pNotifyData,
                              status);

#pragma warning(pop)

   pNotifyData->notificationType = notificationType;
   pNotifyData->calloutID        = pFilter ? pFilter->action.calloutId : 0;
   pNotifyData->pFilterKey       = pFilterKey;

   status = KrnlHlprWorkItemQueue(g_pWDMDevice,
                                  PrvPendAuthorizationNotificationWorkItemRoutine,
                                  pNotifyData);

   HLPR_BAIL_LABEL:

   if(status != STATUS_SUCCESS)
   {
      HLPR_DELETE(pNotifyData,
                  WFPSAMPLER_CALLOUT_DRIVER_TAG);
   }

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

#endif /// DBG
   
   return status;
}
NTSTATUS KrnlHlprRedirectDataCreate(_Outptr_ REDIRECT_DATA** ppRedirectData,
                                    _In_ const VOID* pClassifyContext,
                                    _In_ const FWPS_FILTER* pFilter,
                                    _In_ FWPS_CLASSIFY_OUT* pClassifyOut)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> KrnlHlprRedirectDataCreate()\n");

#endif /// DBG
   
   NT_ASSERT(ppRedirectData);
   NT_ASSERT(pClassifyContext);
   NT_ASSERT(pFilter);
   NT_ASSERT(pClassifyOut);

   NTSTATUS status = STATUS_SUCCESS;

   HLPR_NEW(*ppRedirectData,
            REDIRECT_DATA,
            WFPSAMPLER_SYSLIB_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(*ppRedirectData,
                              status);

   status = KrnlHlprRedirectDataPopulate(*ppRedirectData,
                                         pClassifyContext,
                                         pFilter,
                                         pClassifyOut);

   HLPR_BAIL_LABEL:

#pragma warning(push)
#pragma warning(disable: 6001) /// *ppRedirectData initialized with call to HLPR_NEW & KrnlHlprRedirectDataPopulate 

   if(status != STATUS_SUCCESS &&
      *ppRedirectData)
      KrnlHlprRedirectDataDestroy(ppRedirectData);

#pragma warning(pop)

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

#endif /// DBG
   
   return status;
}
NTSTATUS KrnlHlprWorkItemDataCreate(_Outptr_ WORKITEM_DATA** ppWorkItemData,
                                    _In_ CLASSIFY_DATA* pClassifyData,
                                    _In_ REDIRECT_DATA* pRedirectData,
                                    _In_opt_ PIO_WORKITEM pIOWorkItem,       /* 0 */
                                    _In_opt_ VOID* pContext)                 /* 0 */
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> KrnlHlprWorkItemDataCreate()\n");

#endif /// DBG
   
   NT_ASSERT(ppWorkItemData);
   NT_ASSERT(pClassifyData);
   NT_ASSERT(pRedirectData);

   NTSTATUS status = STATUS_SUCCESS;

   HLPR_NEW(*ppWorkItemData,
            WORKITEM_DATA,
            WFPSAMPLER_SYSLIB_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(*ppWorkItemData,
                              status);

   KrnlHlprWorkItemDataPopulate(*ppWorkItemData,
                                pClassifyData,
                                pRedirectData,
                                pIOWorkItem,
                                pContext);

   HLPR_BAIL_LABEL:

   if(status != STATUS_SUCCESS)
      KrnlHlprWorkItemDataDestroy(ppWorkItemData);

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

#endif /// DBG
   
   return status;
}
NTSTATUS KrnlHlprDPCDataCreate(_Outptr_ DPC_DATA** ppDPCData,
                               _In_ CLASSIFY_DATA* pClassifyData,
                               _In_ PEND_DATA* pPendData,
                               _In_opt_ VOID* pContext)                 /* 0 */
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> KrnlHlprDPCDataCreate()\n");

#endif /// DBG
   
   NT_ASSERT(ppDPCData);
   NT_ASSERT(pClassifyData);
   NT_ASSERT(pPendData);

   NTSTATUS status = STATUS_SUCCESS;

   HLPR_NEW(*ppDPCData,
            DPC_DATA,
            WFPSAMPLER_SYSLIB_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(*ppDPCData,
                              status);

   KrnlHlprDPCDataPopulate(*ppDPCData,
                           pClassifyData,
                           pPendData,
                           pContext);

   HLPR_BAIL_LABEL:

   if(status != STATUS_SUCCESS)
      KrnlHlprDPCDataDestroy(ppDPCData);

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

#endif /// DBG
   
   return status;
}
NTSTATUS KrnlHlprNDISPoolDataCreate(_Outptr_ NDIS_POOL_DATA** ppNDISPoolData,
                                    _In_opt_ UINT32 memoryTag)                /* WFPSAMPLER_NDIS_POOL_TAG */
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> KrnlHlprNDISPoolDataCreate()\n");

#endif /// DBG
   
   NT_ASSERT(ppNDISPoolData);

   NTSTATUS status = STATUS_SUCCESS;

   HLPR_NEW(*ppNDISPoolData,
            NDIS_POOL_DATA,
            WFPSAMPLER_SYSLIB_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(*ppNDISPoolData,
                              status);

   status = KrnlHlprNDISPoolDataPopulate(*ppNDISPoolData,
                                         memoryTag);

   HLPR_BAIL_LABEL:

#pragma warning(push)
#pragma warning(disable: 6001) /// *ppNDISPoolData initialized with calls to HLPR_NEW & KrnlHlprNDISPoolDataPopulate

   if(status != STATUS_SUCCESS &&
      *ppNDISPoolData)
      KrnlHlprNDISPoolDataDestroy(ppNDISPoolData);

#pragma warning(pop)

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

#endif /// DBG
   
   return status;
}
UINT32 HlprThreadPoolDataCreate(_Outptr_ THREADPOOL_DATA** ppThreadPoolData,
                                _In_ const PTP_CLEANUP_GROUP_CANCEL_CALLBACK pGroupCancelFn)
{
   ASSERT(ppThreadPoolData);

   UINT32 status = NO_ERROR;

   HLPR_NEW(*ppThreadPoolData,
            THREADPOOL_DATA);
   HLPR_BAIL_ON_ALLOC_FAILURE(*ppThreadPoolData,
                              status);

   status = HlprThreadPoolDataPopulate(*ppThreadPoolData,
                                       pGroupCancelFn);

   HLPR_BAIL_LABEL:

   if(status != NO_ERROR)
      HlprThreadPoolDataDestroy(ppThreadPoolData);


   return status;
}
NTSTATUS PrvCloneAuthorizedNBLAndInject(_Inout_ CLASSIFY_DATA** ppClassifyData,
                                        _Inout_ INJECTION_DATA** ppInjectionData)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> PrvCloneAuthorizedNBLAndInject()\n");

#endif /// DBG
   
   NT_ASSERT(ppClassifyData);
   NT_ASSERT(ppInjectionData);
   NT_ASSERT(*ppClassifyData);
   NT_ASSERT(*ppInjectionData);

   NTSTATUS                            status          = STATUS_SUCCESS;
   FWPS_INCOMING_VALUES*               pClassifyValues = (FWPS_INCOMING_VALUES*)(*ppClassifyData)->pClassifyValues;
   FWPS_INCOMING_METADATA_VALUES*      pMetadata       = (FWPS_INCOMING_METADATA_VALUES*)(*ppClassifyData)->pMetadataValues;
   UINT32                              bytesRetreated  = 0;
   COMPARTMENT_ID                      compartmentID   = UNSPECIFIED_COMPARTMENT_ID;
   BOOLEAN                             isInbound       = FALSE;
   NET_BUFFER_LIST*                    pNetBufferList  = 0;
   PEND_AUTHORIZATION_COMPLETION_DATA* pCompletionData = 0;
   FWPS_TRANSPORT_SEND_PARAMS*         pSendParams     = 0;
   BYTE*                               pRemoteAddress  = 0;

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

   HLPR_NEW(pCompletionData,
            PEND_AUTHORIZATION_COMPLETION_DATA,
            WFPSAMPLER_CALLOUT_DRIVER_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(pCompletionData,
                              status);

   HLPR_NEW(pSendParams,
            FWPS_TRANSPORT_SEND_PARAMS,
            WFPSAMPLER_CALLOUT_DRIVER_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(pSendParams,
                              status);

#pragma warning(pop)

   KeInitializeSpinLock(&(pCompletionData->spinLock));

   pCompletionData->performedInline = FALSE;
   pCompletionData->pClassifyData   = *ppClassifyData;
   pCompletionData->pInjectionData  = *ppInjectionData;
   pCompletionData->pSendParams     = pSendParams;

   /// Responsibility for freeing this memory has been transferred to the pCompletionData
   *ppClassifyData = 0;

   *ppInjectionData = 0;

   pSendParams = 0;

   if(pCompletionData->pInjectionData->direction == FWP_DIRECTION_INBOUND)
      isInbound = TRUE;

   if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                     FWPS_METADATA_FIELD_COMPARTMENT_ID))
      compartmentID = (COMPARTMENT_ID)pMetadata->compartmentId;

   if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                     FWPS_METADATA_FIELD_IP_HEADER_SIZE))
      bytesRetreated = pMetadata->ipHeaderSize;

   if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                     FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE))
      bytesRetreated += pMetadata->transportHeaderSize;

   if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
      pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6)
   {
      if(isInbound) /// NBL offset is at the start of the transport header ...
      {
         if(bytesRetreated)
         {
            /// so retreat (size of IP Header) to clone the whole NBL
            status = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket),
                                                   bytesRetreated,
                                                   0,
                                                   0);
            if(status != STATUS_SUCCESS)
            {
               DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                          DPFLTR_ERROR_LEVEL,
                          " !!!! PrvCloneAuthorizedNBLAndInject: NdisRetreatNetBufferDataStart() [status: %#x]\n",
                          status);

               HLPR_BAIL;
            }
         }
      }
   }
   else if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
           pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6)
   {
      /// NBL offset is at the Transport Header, and no IP Header is present yet
      bytesRetreated = 0;

      isInbound = FALSE;
   }
   else
   {
      status = STATUS_FWP_INCOMPATIBLE_LAYER;

      HLPR_BAIL;
   }

   status = FwpsAllocateCloneNetBufferList((NET_BUFFER_LIST*)(pCompletionData->pClassifyData->pPacket),
                                           g_pNDISPoolData->nblPoolHandle,
                                           g_pNDISPoolData->nbPoolHandle,
                                           0,
                                           &pNetBufferList);

   if(bytesRetreated)
   {
      /// Advance the NBL offset so we are back at the expected position in the NET_BUFFER_LIST
      NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket),
                                    bytesRetreated,
                                    FALSE,
                                    0);
   }

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

      HLPR_BAIL;
   }

   if(isInbound)
   {
      FWP_VALUE* pInterfaceIndex    = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
                                                                                &FWPM_CONDITION_INTERFACE_INDEX);
      FWP_VALUE* pSubInterfaceIndex = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
                                                                                &FWPM_CONDITION_SUB_INTERFACE_INDEX);
      IF_INDEX   interfaceIndex     = 0;
      IF_INDEX   subInterfaceIndex  = 0;

      if(pInterfaceIndex &&
         pInterfaceIndex->type == FWP_UINT32)
         interfaceIndex = (IF_INDEX)pInterfaceIndex->uint32;

      if(pSubInterfaceIndex &&
         pSubInterfaceIndex->type == FWP_UINT32)
         subInterfaceIndex = (IF_INDEX)pSubInterfaceIndex->uint32;

      status = FwpsInjectTransportReceiveAsync(pCompletionData->pInjectionData->injectionHandle,
                                               pCompletionData->pInjectionData->injectionContext,
                                               0,
                                               0,
                                               pCompletionData->pInjectionData->addressFamily,
                                               compartmentID,
                                               interfaceIndex,
                                               subInterfaceIndex,
                                               pNetBufferList,
                                               CompletePendAuthorization,
                                               pCompletionData);
   }
   else
   {
      UINT64     endpointHandle = 0;
      FWP_VALUE* pAddressValue  = 0;

      if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                        FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE))
         endpointHandle = pMetadata->transportEndpointHandle;

      pAddressValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
                                                                &FWPM_CONDITION_IP_REMOTE_ADDRESS);
      if(pAddressValue)
      {
         if(pCompletionData->pInjectionData->addressFamily == AF_INET)
         {
            UINT32 tempAddress = htonl(pAddressValue->uint32);

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

            HLPR_NEW_ARRAY(pRemoteAddress,
                           BYTE,
                           IPV4_ADDRESS_SIZE,
                           WFPSAMPLER_CALLOUT_DRIVER_TAG);
            HLPR_BAIL_ON_ALLOC_FAILURE(pRemoteAddress,
                                       status);

#pragma warning(pop)

            RtlCopyMemory(pRemoteAddress,
                          &tempAddress,
                          IPV4_ADDRESS_SIZE);
         }
         else
         {

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

            HLPR_NEW_ARRAY(pRemoteAddress,
                           BYTE,
                           IPV6_ADDRESS_SIZE,
                           WFPSAMPLER_CALLOUT_DRIVER_TAG);
            HLPR_BAIL_ON_ALLOC_FAILURE(pRemoteAddress,
                                       status);

#pragma warning(pop)

            RtlCopyMemory(pRemoteAddress,
                          pAddressValue->byteArray16->byteArray16,
                          IPV6_ADDRESS_SIZE);

            if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                              FWPS_METADATA_FIELD_REMOTE_SCOPE_ID))
               pCompletionData->pSendParams->remoteScopeId = pMetadata->remoteScopeId;
         }

         pCompletionData->pSendParams->remoteAddress = pRemoteAddress;
      }

      pCompletionData->refCount = KrnlHlprNBLGetRequiredRefCount(pNetBufferList);

      status = FwpsInjectTransportSendAsync(pCompletionData->pInjectionData->injectionHandle,
                                            pCompletionData->pInjectionData->injectionContext,
                                            endpointHandle,
                                            0,
                                            pCompletionData->pSendParams,
                                            pCompletionData->pInjectionData->addressFamily,
                                            compartmentID,
                                            pNetBufferList,
                                            CompletePendAuthorization,
                                            pCompletionData);
   }

   HLPR_BAIL_LABEL:

   if(status != STATUS_SUCCESS)
   {
      if(pNetBufferList)
      {
         FwpsFreeCloneNetBufferList(pNetBufferList,
                                    0);

         pNetBufferList = 0;
      }

      if(pCompletionData)
         PendAuthorizationCompletionDataDestroy(&pCompletionData,
                                                TRUE);
   }

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

#endif /// DBG
   
   return status;
}
NTSTATUS KrnlHlprClassifyDataCreateLocalCopy(_Outptr_ CLASSIFY_DATA** ppClassifyData,
                                             _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,
              " ---> KrnlHlprClassifyDataCreateLocalCopy()\n");

#endif /// DBG
   
   NT_ASSERT(ppClassifyData);
   NT_ASSERT(pClassifyValues);
   NT_ASSERT(pMetadata);
   NT_ASSERT(pFilter);
   NT_ASSERT(pClassifyOut);

   NTSTATUS status = STATUS_SUCCESS;

   HLPR_NEW(*ppClassifyData,
            CLASSIFY_DATA,
            WFPSAMPLER_SYSLIB_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(*ppClassifyData,
                              status);

   status = KrnlHlprClassifyDataAcquireLocalCopy(*ppClassifyData,
                                                 pClassifyValues,
                                                 pMetadata,
                                                 pPacket,
                                                 pClassifyContext,
                                                 pFilter,
                                                 flowContext,
                                                 pClassifyOut);

   HLPR_BAIL_LABEL:

#pragma warning(push)
#pragma warning(disable: 6001) /// *ppClassifyData initialized with call to HLPR_NEW & KrnlHlprClassifyDataAcquireLocalCopy 

   if(status != STATUS_SUCCESS &&
      *ppClassifyData)
      KrnlHlprClassifyDataDestroyLocalCopy(ppClassifyData);

#pragma warning(pop)

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

#endif /// DBG

   return status;
}
UINT32 WindowsFirewallAcquireFirewallCategory()
{
    UINT32 status = NO_ERROR;

    if(HlprServiceQueryState(L"MPSSvc") == SERVICE_RUNNING)
    {
        BSTR            pProductName      = SysAllocString(g_pServiceName);
        INetFwProduct*  pNetFwProduct     = 0;
        INetFwProducts* pNetFwProducts    = 0;
        SAFEARRAY*      pFirewallCategory = 0;
        SAFEARRAY*      pBootTimeCategory = 0;
        SAFEARRAYBOUND  boundary          = {0};
        VARIANT         firewallCategory  = {0};
        VARIANT         boottimeCategory  = {0};

        if(pProductName == 0)
        {
            status = ERROR_GEN_FAILURE;

            ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : SysAllocString()",
                                 status);

            HLPR_BAIL;
        }

        boundary.lLbound   = 0;
        boundary.cElements = 1;

        pBootTimeCategory = SafeArrayCreate(VT_VARIANT,
                                            1,
                                            &boundary);
        if(pBootTimeCategory == 0)
        {
            status = ERROR_GEN_FAILURE;

            ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : SafeArrayCreate()",
                                 status);

            HLPR_BAIL;
        }

        V_VT((VARIANT*)pBootTimeCategory->pvData) = VT_I4;
        V_I4((VARIANT*)pBootTimeCategory->pvData) = NET_FW_RULE_CATEGORY_BOOT;

        VariantInit(&firewallCategory);

        V_VT(&boottimeCategory)    = VT_ARRAY | VT_VARIANT;
        V_ARRAY(&boottimeCategory) = pBootTimeCategory;

        pFirewallCategory = SafeArrayCreate(VT_VARIANT,
                                            1,
                                            &boundary);
        if(pFirewallCategory == 0)
        {
            status = ERROR_GEN_FAILURE;

            ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : SafeArrayCreate()",
                                 status);

            HLPR_BAIL;
        }

        V_VT((VARIANT*)pFirewallCategory->pvData) = VT_I4;
        V_I4((VARIANT*)pFirewallCategory->pvData) = NET_FW_RULE_CATEGORY_FIREWALL;

        VariantInit(&firewallCategory);

        V_VT(&firewallCategory)    = VT_ARRAY | VT_VARIANT;
        V_ARRAY(&firewallCategory) = pFirewallCategory;

        /// Initialize the COM library
        if(!g_isCOMInitialized)
        {
            status = CoInitializeEx(0,
                                    COINIT_MULTITHREADED);
            if(FAILED(status))
            {
                ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : CoInitializeEx()",
                                     status);

                HLPR_BAIL;
            }

            g_isCOMInitialized = TRUE;
        }

        /// Create an instance of the NetFwProduct class
        status = CoCreateInstance(__uuidof(NetFwProduct),
                                  0,
                                  CLSCTX_INPROC_SERVER,
                                  __uuidof(INetFwProduct),
                                  (LPVOID*)&pNetFwProduct);
        if(FAILED(status))
        {
            ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : CoCreateInstance()",
                                 status);

            HLPR_BAIL;
        }

        /// Set the DisplayName
        status = pNetFwProduct->put_DisplayName(pProductName);
        if(FAILED(status))
        {
            ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : INetFwProduct::put_DisplayName()",
                                 status);

            HLPR_BAIL;
        }

        /// Take the category
        status = pNetFwProduct->put_RuleCategories(boottimeCategory);
        if(FAILED(status))
        {
            ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : INetFwProduct::put_RuleCategories()",
                                 status);

            HLPR_BAIL;
        }

        status = pNetFwProduct->put_RuleCategories(firewallCategory);
        if(FAILED(status))
        {
            ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : INetFwProduct::put_RuleCategories()",
                                 status);

            HLPR_BAIL;
        }

        /// Create an instance of the NetFwProducts class
        status = CoCreateInstance(__uuidof(NetFwProducts),
                                  0,
                                  CLSCTX_INPROC_SERVER,
                                  __uuidof(INetFwProducts),
                                  (LPVOID*)&pNetFwProducts);
        if(FAILED(status))
        {
            ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : CoCreateInstance()",
                                 status);

            HLPR_BAIL;
        }

        /// Register as a Firewall Product
        if(pFirewallRegistrationHandle == 0)
        {
            status = pNetFwProducts->Register(pNetFwProduct,
                                              &pFirewallRegistrationHandle);
            if(FAILED(status))
            {
                ServiceEventLogError(L"WindowsFirewallAcquireFirewallCategory : INetFwProducts::Register()",
                                     status);

                HLPR_BAIL;
            }
        }

        status = NO_ERROR;

HLPR_BAIL_LABEL:

        if(FAILED(status))
            WindowsFirewallReleaseFirewallCategory();

        if(pNetFwProducts)
            pNetFwProducts->Release();

        if(pNetFwProduct)
            pNetFwProduct->Release();

        if(pProductName)
            SysFreeString(pProductName);
    }
    else
    {
        HLPR_NEW(pWFNotifyThread,
                 THREAD_DATA);
        if(pWFNotifyThread)
        {
            pWFNotifyThread->threadStartRoutine = (LPTHREAD_START_ROUTINE)WindowsFirewallNotifyThreadStartRoutine;

            status = HlprThreadStart(pWFNotifyThread);
        }
        else
            status = ERROR_OUTOFMEMORY;
    }

    if(HlprServiceQueryState(L"WFPSampler") == SERVICE_START_PENDING)
        ServiceStatusReportToSCM(SERVICE_START_PENDING,
                                 status,
                                 2500);

    return status;
}
NTSTATUS KrnlHlprPendDataCreate(_Outptr_ PEND_DATA** ppPendData,
                                _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,
              " ---> KrnlHlprPendDataCreate()\n");

#endif /// DBG
   
   NT_ASSERT(ppPendData);
   NT_ASSERT(pClassifyValues);
   NT_ASSERT(pMetadata);
   NT_ASSERT(pFilter);

   NTSTATUS status = STATUS_SUCCESS;

   HLPR_NEW(*ppPendData,
            PEND_DATA,
            WFPSAMPLER_SYSLIB_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(*ppPendData,
                              status);

   status = KrnlHlprPendDataPopulate(*ppPendData,
                                     pClassifyValues,
                                     pMetadata,
                                     pNBL,
                                     pFilter,
                                     pClassifyContext,
                                     pClassifyOut);

   HLPR_BAIL_LABEL:

#pragma warning(push)
#pragma warning(disable: 6001) /// *ppPendData initialized with calls to HLPR_NEW & KrnlHlprPendDataPopulate 

   if(status != STATUS_SUCCESS &&
      *ppPendData)
      KrnlHlprPendDataDestroy(ppPendData);

#pragma warning(pop)

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- KrnlHlprPendDataCreate() [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;
}