title: NDIS filter driver' FilterReceiveNetBufferLists handler isn't called
body: <p>I am developing an NDIS filter driver, and I fount its <code>FilterReceiveNetBufferLists</code> is never called (the network is blocked) under certain condition (like open Wireshark or click the "Interface List" button of it). But When I start the capturing, the <code>FilterReceiveNetBufferLists</code> get to be normal (network restored), this is so strange. </p>
  
  <p>I found that when I mannually return <code>NDIS_STATUS_FAILURE</code> for the <code>NdisFOidRequest</code> function in an OID originating place of WinPcap driver (BIOCQUERYOID &amp; BIOCSETOID switch branch of NPF_IoControl), then driver won't block the network (Also the winpcap can't work). </p>
  
  <p><strong>Is there something wrong with the <code>NdisFOidRequest</code> call?</strong>  </p>
  
  <p>The DeviceIO routine in Packet.c that originates OID requests:</p>
  
  <pre><code>case BIOCQUERYOID:
  case BIOCSETOID:
  
      TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETOID - BIOCQUERYOID");
  
      //
      // gain ownership of the Ndis Handle
      //
      if (NPF_StartUsingBinding(Open) == FALSE)
      {
          //
          // MAC unbindind or unbound
          //
          SET_FAILURE_INVALID_REQUEST();
          break;
      }
  
  
      // Extract a request from the list of free ones
      RequestListEntry = ExInterlockedRemoveHeadList(&amp;Open-&gt;RequestList, &amp;Open-&gt;RequestSpinLock);
      if (RequestListEntry == NULL)
      {
          //
          // Release ownership of the Ndis Handle
          //
          NPF_StopUsingBinding(Open);
  
          SET_FAILURE_NOMEM();
          break;
      }
  
      pRequest = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
  
      //
      //  See if it is an Ndis request
      //
      OidData = Irp-&gt;AssociatedIrp.SystemBuffer;
  
      if ((IrpSp-&gt;Parameters.DeviceIoControl.InputBufferLength == IrpSp-&gt;Parameters.DeviceIoControl.OutputBufferLength) &amp;&amp;
          (IrpSp-&gt;Parameters.DeviceIoControl.InputBufferLength &gt;= sizeof(PACKET_OID_DATA)) &amp;&amp;
          (IrpSp-&gt;Parameters.DeviceIoControl.InputBufferLength &gt;= sizeof(PACKET_OID_DATA) - 1 + OidData-&gt;Length))
      {
          TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "BIOCSETOID|BIOCQUERYOID Request: Oid=%08lx, Length=%08lx", OidData-&gt;Oid, OidData-&gt;Length);
  
          //
          //  The buffer is valid
          //
          NdisZeroMemory(&amp;pRequest-&gt;Request, sizeof(NDIS_OID_REQUEST));
          pRequest-&gt;Request.Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
          pRequest-&gt;Request.Header.Revision = NDIS_OID_REQUEST_REVISION_1;
          pRequest-&gt;Request.Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;
  
          if (FunctionCode == BIOCSETOID)
          {
              pRequest-&gt;Request.RequestType = NdisRequestSetInformation;
              pRequest-&gt;Request.DATA.SET_INFORMATION.Oid = OidData-&gt;Oid;
  
              pRequest-&gt;Request.DATA.SET_INFORMATION.InformationBuffer = OidData-&gt;Data;
              pRequest-&gt;Request.DATA.SET_INFORMATION.InformationBufferLength = OidData-&gt;Length;
          }
          else
          {
              pRequest-&gt;Request.RequestType = NdisRequestQueryInformation;
              pRequest-&gt;Request.DATA.QUERY_INFORMATION.Oid = OidData-&gt;Oid;
  
              pRequest-&gt;Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData-&gt;Data;
              pRequest-&gt;Request.DATA.QUERY_INFORMATION.InformationBufferLength = OidData-&gt;Length;
          }
  
          NdisResetEvent(&amp;pRequest-&gt;InternalRequestCompletedEvent);
  
          if (*((PVOID *) pRequest-&gt;Request.SourceReserved) != NULL)
          {
              *((PVOID *) pRequest-&gt;Request.SourceReserved) = NULL;
          }
          //
          //  submit the request
          //
          pRequest-&gt;Request.RequestId = (PVOID) NPF6X_REQUEST_ID;
          ASSERT(Open-&gt;AdapterHandle != NULL);
          Status = NdisFOidRequest(Open-&gt;AdapterHandle, &amp;pRequest-&gt;Request);
          //Status = NDIS_STATUS_FAILURE;
      }
      else
      {
          //
          // Release ownership of the Ndis Handle
          //
          NPF_StopUsingBinding(Open);
  
          //
          //  buffer too small
          //
          SET_FAILURE_BUFFER_SMALL();
          break;
      }
  
      if (Status == NDIS_STATUS_PENDING)
      {
          NdisWaitEvent(&amp;pRequest-&gt;InternalRequestCompletedEvent, 1000);
          Status = pRequest-&gt;RequestStatus;
      }
  
      //
      // Release ownership of the Ndis Handle
      //
      NPF_StopUsingBinding(Open);
  
      //
      // Complete the request
      //
      if (FunctionCode == BIOCSETOID)
      {
          OidData-&gt;Length = pRequest-&gt;Request.DATA.SET_INFORMATION.BytesRead;
          TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "BIOCSETOID completed, BytesRead = %u", OidData-&gt;Length);
      }
      else
      {
          if (FunctionCode == BIOCQUERYOID)
          {
              OidData-&gt;Length = pRequest-&gt;Request.DATA.QUERY_INFORMATION.BytesWritten;
  
              if (Status == NDIS_STATUS_SUCCESS)
              {
                  //
                  // check for the stupid bug of the Nortel driver ipsecw2k.sys v. 4.10.0.0 that doesn't set the BytesWritten correctly
                  // The driver is the one shipped with Nortel client Contivity VPN Client V04_65.18, and the MD5 for the buggy (unsigned) driver
                  // is 3c2ff8886976214959db7d7ffaefe724 *ipsecw2k.sys (there are multiple copies of this binary with the same exact version info!)
                  // 
                  // The (certified) driver shipped with Nortel client Contivity VPN Client V04_65.320 doesn't seem affected by the bug.
                  //
                  if (pRequest-&gt;Request.DATA.QUERY_INFORMATION.BytesWritten &gt; pRequest-&gt;Request.DATA.QUERY_INFORMATION.InformationBufferLength)
                  {
                      TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "Bogus return from NdisRequest (query): Bytes Written (%u) &gt; InfoBufferLength (%u)!!", pRequest-&gt;Request.DATA.QUERY_INFORMATION.BytesWritten, pRequest-&gt;Request.DATA.QUERY_INFORMATION.InformationBufferLength);
  
                      Status = NDIS_STATUS_INVALID_DATA;
                  }
              }
  
              TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "BIOCQUERYOID completed, BytesWritten = %u", OidData-&gt;Length);
          }
      }
  
  
      ExInterlockedInsertTailList(&amp;Open-&gt;RequestList, &amp;pRequest-&gt;ListElement, &amp;Open-&gt;RequestSpinLock);
  
      if (Status == NDIS_STATUS_SUCCESS)
      {
          SET_RESULT_SUCCESS(sizeof(PACKET_OID_DATA) - 1 + OidData-&gt;Length);
      }
      else
      {
          SET_FAILURE_INVALID_REQUEST();
      }
  
      break;
  </code></pre>
  
  <p><strong>Three Filter OID routines:</strong></p>
  
  <pre><code>_Use_decl_annotations_
  NDIS_STATUS
  NPF_OidRequest(
      NDIS_HANDLE         FilterModuleContext,
      PNDIS_OID_REQUEST   Request
      )
  {
      POPEN_INSTANCE          Open = (POPEN_INSTANCE) FilterModuleContext;
      NDIS_STATUS             Status;
      PNDIS_OID_REQUEST       ClonedRequest=NULL;
      BOOLEAN                 bSubmitted = FALSE;
      PFILTER_REQUEST_CONTEXT Context;
      BOOLEAN                 bFalse = FALSE;
  
      TRACE_ENTER();
  
      do
      {
          Status = NdisAllocateCloneOidRequest(Open-&gt;AdapterHandle,
                                              Request,
                                              NPF6X_ALLOC_TAG,
                                              &amp;ClonedRequest);
          if (Status != NDIS_STATUS_SUCCESS)
          {
              TRACE_MESSAGE(PACKET_DEBUG_LOUD, "FilerOidRequest: Cannot Clone Request\n");
              break;
          }
  
          Context = (PFILTER_REQUEST_CONTEXT)(&amp;ClonedRequest-&gt;SourceReserved[0]);
          *Context = Request;
  
          bSubmitted = TRUE;
  
          //
          // Use same request ID
          //
          ClonedRequest-&gt;RequestId = Request-&gt;RequestId;
  
          Open-&gt;PendingOidRequest = ClonedRequest;
  
          Status = NdisFOidRequest(Open-&gt;AdapterHandle, ClonedRequest);
  
          if (Status != NDIS_STATUS_PENDING)
          {
              NPF_OidRequestComplete(Open, ClonedRequest, Status);
              Status = NDIS_STATUS_PENDING;
          }
  
  
      }while (bFalse);
  
      if (bSubmitted == FALSE)
      {
          switch(Request-&gt;RequestType)
          {
              case NdisRequestMethod:
                  Request-&gt;DATA.METHOD_INFORMATION.BytesRead = 0;
                  Request-&gt;DATA.METHOD_INFORMATION.BytesNeeded = 0;
                  Request-&gt;DATA.METHOD_INFORMATION.BytesWritten = 0;
                  break;
  
              case NdisRequestSetInformation:
                  Request-&gt;DATA.SET_INFORMATION.BytesRead = 0;
                  Request-&gt;DATA.SET_INFORMATION.BytesNeeded = 0;
                  break;
  
              case NdisRequestQueryInformation:
              case NdisRequestQueryStatistics:
              default:
                  Request-&gt;DATA.QUERY_INFORMATION.BytesWritten = 0;
                  Request-&gt;DATA.QUERY_INFORMATION.BytesNeeded = 0;
                  break;
          }
  
      }
  
      TRACE_EXIT();
      return Status;
  
  }
  
  //-------------------------------------------------------------------
  
  _Use_decl_annotations_
  VOID
  NPF_CancelOidRequest(
      NDIS_HANDLE             FilterModuleContext,
      PVOID                   RequestId
      )
  {
      POPEN_INSTANCE                      Open = (POPEN_INSTANCE) FilterModuleContext;
      PNDIS_OID_REQUEST                   Request = NULL;
      PFILTER_REQUEST_CONTEXT             Context;
      PNDIS_OID_REQUEST                   OriginalRequest = NULL;
      BOOLEAN                             bFalse = FALSE;
  
      FILTER_ACQUIRE_LOCK(&amp;Open-&gt;OIDLock, bFalse);
  
      Request = Open-&gt;PendingOidRequest;
  
      if (Request != NULL)
      {
          Context = (PFILTER_REQUEST_CONTEXT)(&amp;Request-&gt;SourceReserved[0]);
  
          OriginalRequest = (*Context);
      }
  
      if ((OriginalRequest != NULL) &amp;&amp; (OriginalRequest-&gt;RequestId == RequestId))
      {
          FILTER_RELEASE_LOCK(&amp;Open-&gt;OIDLock, bFalse);
  
          NdisFCancelOidRequest(Open-&gt;AdapterHandle, RequestId);
      }
      else
      {
          FILTER_RELEASE_LOCK(&amp;Open-&gt;OIDLock, bFalse);
      }
  }
  
  //-------------------------------------------------------------------
  
  _Use_decl_annotations_
  VOID
  NPF_OidRequestComplete(
      NDIS_HANDLE         FilterModuleContext,
      PNDIS_OID_REQUEST   Request,
      NDIS_STATUS         Status
      )
  {
      POPEN_INSTANCE                      Open = (POPEN_INSTANCE) FilterModuleContext;
      PNDIS_OID_REQUEST                   OriginalRequest;
      PFILTER_REQUEST_CONTEXT             Context;
      BOOLEAN                             bFalse = FALSE;
  
      TRACE_ENTER();
  
      Context = (PFILTER_REQUEST_CONTEXT)(&amp;Request-&gt;SourceReserved[0]);
      OriginalRequest = (*Context);
  
      //
      // This is an internal request
      //
      if (OriginalRequest == NULL)
      {
          TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Status= %p", Status);
          NPF_InternalRequestComplete(Open, Request, Status);
          TRACE_EXIT();
          return;
      }
  
  
      FILTER_ACQUIRE_LOCK(&amp;Open-&gt;OIDLock, bFalse);
  
      ASSERT(Open-&gt;PendingOidRequest == Request);
      Open-&gt;PendingOidRequest = NULL;
  
      FILTER_RELEASE_LOCK(&amp;Open-&gt;OIDLock, bFalse);
  
  
      //
      // Copy the information from the returned request to the original request
      //
      switch(Request-&gt;RequestType)
      {
          case NdisRequestMethod:
              OriginalRequest-&gt;DATA.METHOD_INFORMATION.OutputBufferLength =  Request-&gt;DATA.METHOD_INFORMATION.OutputBufferLength;
              OriginalRequest-&gt;DATA.METHOD_INFORMATION.BytesRead = Request-&gt;DATA.METHOD_INFORMATION.BytesRead;
              OriginalRequest-&gt;DATA.METHOD_INFORMATION.BytesNeeded = Request-&gt;DATA.METHOD_INFORMATION.BytesNeeded;
              OriginalRequest-&gt;DATA.METHOD_INFORMATION.BytesWritten = Request-&gt;DATA.METHOD_INFORMATION.BytesWritten;
              break;
  
          case NdisRequestSetInformation:
              OriginalRequest-&gt;DATA.SET_INFORMATION.BytesRead = Request-&gt;DATA.SET_INFORMATION.BytesRead;
              OriginalRequest-&gt;DATA.SET_INFORMATION.BytesNeeded = Request-&gt;DATA.SET_INFORMATION.BytesNeeded;
              break;
  
          case NdisRequestQueryInformation:
          case NdisRequestQueryStatistics:
          default:
              OriginalRequest-&gt;DATA.QUERY_INFORMATION.BytesWritten = Request-&gt;DATA.QUERY_INFORMATION.BytesWritten;
              OriginalRequest-&gt;DATA.QUERY_INFORMATION.BytesNeeded = Request-&gt;DATA.QUERY_INFORMATION.BytesNeeded;
              break;
      }
  
  
      (*Context) = NULL;
  
      NdisFreeCloneOidRequest(Open-&gt;AdapterHandle, Request);
  
      NdisFOidRequestComplete(Open-&gt;AdapterHandle, OriginalRequest, Status);
  
      TRACE_EXIT();
  }
  </code></pre>