⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miniport.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
 *     TRUE if the destination address is that of the adapter, FALSE if not
 */
{
  UINT Length;
  PUCHAR Start1;
  PUCHAR Start2;
  PNDIS_BUFFER NdisBuffer;
  UINT BufferLength;

  NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));

#ifdef DBG
  if(!Adapter)
    {
      NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
      return FALSE;
    }

  if(!Packet)
    {
      NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
      return FALSE;
    }
#endif

  NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);

  if (!NdisBuffer)
    {
      NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
      return FALSE;
    }

  NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);

  /* FIXME: Should handle fragmented packets */

  switch (Adapter->NdisMiniportBlock.MediaType)
    {
      case NdisMedium802_3:
        Length = ETH_LENGTH_OF_ADDRESS;
        /* Destination address is the first field */
        break;

      default:
        NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
        return FALSE;
    }

  if (BufferLength < Length)
    {
        NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
        return FALSE;
    }

  Start1 = (PUCHAR)&Adapter->Address;
  NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
      *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
      *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5))
  );

  return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
}


PLOGICAL_ADAPTER
MiniLocateDevice(
    PNDIS_STRING AdapterName)
/*
 * FUNCTION: Finds an adapter object by name
 * ARGUMENTS:
 *     AdapterName = Pointer to name of adapter
 * RETURNS:
 *     Pointer to logical adapter object, or NULL if none was found.
 *     If found, the adapter is referenced for the caller. The caller
 *     is responsible for dereferencing after use
 */
{
  KIRQL OldIrql;
  PLIST_ENTRY CurrentEntry;
  PLOGICAL_ADAPTER Adapter = 0;

  ASSERT(AdapterName);

  NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));

  if(IsListEmpty(&AdapterListHead))
    {
      NDIS_DbgPrint(DEBUG_MINIPORT, ("No registered miniports for protocol to bind to\n"));
      return NULL;
    }

  KeAcquireSpinLock(&AdapterListLock, &OldIrql);
    {
      CurrentEntry = AdapterListHead.Flink;
	
      while (CurrentEntry != &AdapterListHead)
        {
	  Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);

	  ASSERT(Adapter);

	  NDIS_DbgPrint(DEBUG_MINIPORT, ("Examining adapter 0x%lx\n", Adapter));
	  NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
	  NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
	    
	  if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
	    {
	      break;
	    }
	    
	  Adapter = NULL;
	  CurrentEntry = CurrentEntry->Flink;
        }
    }
  KeReleaseSpinLock(&AdapterListLock, OldIrql);

  if(Adapter)
    {
      NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
    }
  else
    {
      NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
    }

  return Adapter;
}


NDIS_STATUS
MiniQueryInformation(
    PLOGICAL_ADAPTER    Adapter,
    NDIS_OID            Oid,
    ULONG               Size,
    PVOID               Buffer,
    PULONG              BytesWritten)
/*
 * FUNCTION: Queries a logical adapter for properties
 * ARGUMENTS:
 *     Adapter      = Pointer to the logical adapter object to query
 *     Oid          = Specifies the Object ID to query for
 *     Size         = Size of the passed buffer
 *     Buffer       = Buffer for the output
 *     BytesWritten = Address of buffer to place number of bytes written
 * NOTES:
 *     If the specified buffer is too small, a new buffer is allocated,
 *     and the query is attempted again
 * RETURNS:
 *     Status of operation
 * TODO:
 *     Is there any way to use the buffer provided by the protocol?
 */
{
  NDIS_STATUS NdisStatus;
  ULONG BytesNeeded;

  NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));

  /* call the miniport's queryinfo handler */
  NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
      Adapter->NdisMiniportBlock.MiniportAdapterContext,
      Oid,
      Buffer,
      Size,
      BytesWritten,
      &BytesNeeded);

  /* FIXME: Wait in pending case! */

  /* XXX is status_pending part of success macro? */
  if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING))
    {
      NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
      return NdisStatus;
    }

  return NdisStatus;
}


NDIS_STATUS
FASTCALL
MiniQueueWorkItem(
    PLOGICAL_ADAPTER     Adapter,
    NDIS_WORK_ITEM_TYPE  WorkItemType,
    PVOID                WorkItemContext)
/*
 * FUNCTION: Queues a work item for execution at a later time
 * ARGUMENTS:
 *     Adapter         = Pointer to the logical adapter object to queue work item on
 *     WorkItemType    = Type of work item to queue
 *     WorkItemContext = Pointer to context information for work item
 * NOTES:
 *     Adapter lock must be held when called
 * RETURNS:
 *     Status of operation
 */
{
    PNDIS_MINIPORT_WORK_ITEM Item;

    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
    
    ASSERT(Adapter);
    ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
    
    Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
    if (Item == NULL)
    {
        NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
        return NDIS_STATUS_RESOURCES;
    }
    
    Item->WorkItemType    = WorkItemType;
    Item->WorkItemContext = WorkItemContext;
    
    /* safe due to adapter lock held */
    Item->Link.Next = NULL;
    if (!Adapter->WorkQueueHead)
    {
        Adapter->WorkQueueHead = Item;
        Adapter->WorkQueueTail = Item;
    }
    else
    {
        Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
        Adapter->WorkQueueTail = Item;
    }
    
    KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
    
    return NDIS_STATUS_SUCCESS;
}


NDIS_STATUS
FASTCALL
MiniDequeueWorkItem(
    PLOGICAL_ADAPTER    Adapter,
    NDIS_WORK_ITEM_TYPE *WorkItemType,
    PVOID               *WorkItemContext)
/*
 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
 * ARGUMENTS:
 *     Adapter         = Pointer to the logical adapter object to dequeue work item from
 *     AdapterBinding  = Address of buffer for adapter binding for this request
 *     WorkItemType    = Address of buffer for work item type
 *     WorkItemContext = Address of buffer for pointer to context information
 * NOTES:
 *     Adapter lock must be held when called
 * RETURNS:
 *     Status of operation
 */
{
    PNDIS_MINIPORT_WORK_ITEM Item;
    
    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
    
    Item = Adapter->WorkQueueHead;
    
    if (Item)
    {
        /* safe due to adapter lock held */
        Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
        
        if (Item == Adapter->WorkQueueTail)
            Adapter->WorkQueueTail = NULL;
        
        *WorkItemType    = Item->WorkItemType;
        *WorkItemContext = Item->WorkItemContext;
        
        ExFreePool(Item);
        
        return NDIS_STATUS_SUCCESS;
    }
    
    return NDIS_STATUS_FAILURE;
}


NDIS_STATUS
MiniDoRequest(
    PNDIS_MINIPORT_BLOCK Adapter,
    PNDIS_REQUEST NdisRequest)
/*
 * FUNCTION: Sends a request to a miniport
 * ARGUMENTS:
 *     AdapterBinding = Pointer to binding used in the request
 *     NdisRequest    = Pointer to NDIS request structure describing request
 * RETURNS:
 *     Status of operation
 */
{
    NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
    
    Adapter->MediaRequest = NdisRequest;
    
    switch (NdisRequest->RequestType)
    {
    case NdisRequestQueryInformation:
        return (*Adapter->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
            Adapter->MiniportAdapterContext,
            NdisRequest->DATA.QUERY_INFORMATION.Oid,
            NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
            NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
            (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
            (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
        break;
        
    case NdisRequestSetInformation:
        return (*Adapter->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
            Adapter->MiniportAdapterContext,
            NdisRequest->DATA.SET_INFORMATION.Oid,
            NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
            NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
            (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
            (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
        break;
        
    default:
        return NDIS_STATUS_FAILURE;
    }
}


/*
 * @implemented
 */
#undef NdisMQueryInformationComplete
VOID
EXPORT
NdisMQueryInformationComplete(
    IN  NDIS_HANDLE MiniportAdapterHandle,
    IN  NDIS_STATUS Status)
{
    PNDIS_MINIPORT_BLOCK MiniportBlock =
	(PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
    ASSERT(MiniportBlock);
    if( MiniportBlock->QueryCompleteHandler )
	(MiniportBlock->QueryCompleteHandler)(MiniportAdapterHandle, Status);
}


VOID NTAPI MiniportDpc(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2)
/*
 * FUNCTION: Deferred routine to handle serialization
 * ARGUMENTS:
 *     Dpc             = Pointer to DPC object
 *     DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
 *     SystemArgument1 = Unused
 *     SystemArgument2 = Unused
 */
{
  NDIS_STATUS NdisStatus;
  PVOID WorkItemContext;
  NDIS_WORK_ITEM_TYPE WorkItemType;
  PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);

  NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));

  NdisStatus = 
      MiniDequeueWorkItem
      (Adapter, &WorkItemType, &WorkItemContext);

  if (NdisStatus == NDIS_STATUS_SUCCESS)
    {
      switch (WorkItemType)
        {
          case NdisWorkItemSend:
            /*
             * called by ProSend when protocols want to send packets to the miniport
             */
#ifdef DBG
            MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
#endif
            if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
              {
                NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));

                /*
                 * XXX assumes single-packet - prolly OK since we'll call something
                 * different on multi-packet sends
                 */
                (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
                    Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
		NdisStatus =
		    NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);

                NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
              }
            else
              {
                NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));

                NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
                    Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);

                NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
              }
	    if( NdisStatus != NDIS_STATUS_PENDING ) {
		NdisMSendComplete
		    ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
		Adapter->MiniportBusy = FALSE;
	    }
            break;

          case NdisWorkItemSendLoopback:
            /*
             * called by ProSend when protocols want to send loopback packets
             */
            /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -