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 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;
}