📄 miniport.c
字号:
* 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 + -