2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/protocol.c
5 * PURPOSE: Routines used by NDIS protocol drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 09-13-2003 Vizzini Updates for SendPackets support
15 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
16 #define LINKAGE_KEY L"\\Linkage"
17 #define PARAMETERS_KEY L"\\Parameters\\"
19 LIST_ENTRY ProtocolListHead
;
20 KSPIN_LOCK ProtocolListLock
;
24 typedef struct _DMA_CONTEXT
{
25 PLOGICAL_ADAPTER Adapter
;
27 } DMA_CONTEXT
, *PDMA_CONTEXT
;
31 NET_PNP_EVENT_CODE EventCode
,
33 ULONG EventBufferLength
)
35 PNET_PNP_EVENT PnPEvent
;
37 PnPEvent
= ExAllocatePool(PagedPool
, sizeof(NET_PNP_EVENT
));
39 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
43 RtlZeroMemory(PnPEvent
, sizeof(NET_PNP_EVENT
));
45 PnPEvent
->NetEvent
= EventCode
;
47 if (EventBuffer
!= NULL
)
49 PnPEvent
->Buffer
= ExAllocatePool(PagedPool
, EventBufferLength
);
50 if (!PnPEvent
->Buffer
)
52 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
57 PnPEvent
->BufferLength
= EventBufferLength
;
59 RtlCopyMemory(PnPEvent
->Buffer
, EventBuffer
, PnPEvent
->BufferLength
);
66 ProSendAndFreePnPEvent(
67 PLOGICAL_ADAPTER Adapter
,
68 PNET_PNP_EVENT PnPEvent
,
71 PLIST_ENTRY CurrentEntry
;
73 PADAPTER_BINDING AdapterBinding
;
75 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
77 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
79 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
81 Status
= (*AdapterBinding
->ProtocolBinding
->Chars
.PnPEventHandler
)(
82 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
85 if (Status
== NDIS_STATUS_PENDING
)
87 IoMarkIrpPending(Irp
);
88 /* Yes, I know this is stupid */
89 PnPEvent
->NdisReserved
[0] = (ULONG_PTR
)Irp
;
90 PnPEvent
->NdisReserved
[1] = (ULONG_PTR
)CurrentEntry
->Flink
;
91 return NDIS_STATUS_PENDING
;
93 else if (Status
!= NDIS_STATUS_SUCCESS
)
95 if (PnPEvent
->Buffer
) ExFreePool(PnPEvent
->Buffer
);
100 CurrentEntry
= CurrentEntry
->Flink
;
103 if (PnPEvent
->Buffer
) ExFreePool(PnPEvent
->Buffer
);
104 ExFreePool(PnPEvent
);
106 return NDIS_STATUS_SUCCESS
;
112 IN PDEVICE_OBJECT DeviceObject
,
115 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
116 PNET_PNP_EVENT PnPEvent
;
117 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
119 ASSERT(Stack
->Parameters
.Power
.Type
== DevicePowerState
);
121 PnPEvent
= ProSetupPnPEvent(NetEventSetPower
, &Stack
->Parameters
.Power
.State
, sizeof(NDIS_DEVICE_POWER_STATE
));
123 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
124 return NDIS_STATUS_RESOURCES
;
127 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
133 IN PDEVICE_OBJECT DeviceObject
,
136 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
137 PNET_PNP_EVENT PnPEvent
;
138 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
140 ASSERT(Stack
->Parameters
.Power
.Type
== DevicePowerState
);
142 PnPEvent
= ProSetupPnPEvent(NetEventQueryPower
, &Stack
->Parameters
.Power
.State
, sizeof(NDIS_DEVICE_POWER_STATE
));
144 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
145 return NDIS_STATUS_RESOURCES
;
148 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
154 NdisIPnPQueryStopDevice(
155 IN PDEVICE_OBJECT DeviceObject
,
158 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
159 PNET_PNP_EVENT PnPEvent
;
161 PnPEvent
= ProSetupPnPEvent(NetEventQueryRemoveDevice
, NULL
, 0);
163 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
164 return NDIS_STATUS_RESOURCES
;
167 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
172 NdisIPnPCancelStopDevice(
173 IN PDEVICE_OBJECT DeviceObject
,
176 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
177 PNET_PNP_EVENT PnPEvent
;
179 PnPEvent
= ProSetupPnPEvent(NetEventCancelRemoveDevice
, NULL
, 0);
181 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
182 return NDIS_STATUS_RESOURCES
;
185 return ProSendAndFreePnPEvent(Adapter
, PnPEvent
, Irp
);
194 NdisCompleteBindAdapter(
195 IN NDIS_HANDLE BindAdapterContext
,
196 IN NDIS_STATUS Status
,
197 IN NDIS_STATUS OpenStatus
)
199 * FUNCTION: Indicates a packet to bound protocols
201 * Adapter = Pointer to logical adapter
202 * Packet = Pointer to packet to indicate
204 * Status of operation
206 * - FIXME: partially-implemented
209 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)BindAdapterContext
;
211 if (!NT_SUCCESS(Status
)) {
212 NDIS_DbgPrint(MIN_TRACE
, ("Binding failed (%x)\n", Status
));
216 /* Put protocol binding struct on global list */
217 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
225 NdisCompleteUnbindAdapter(
226 IN NDIS_HANDLE UnbindAdapterContext
,
227 IN NDIS_STATUS Status
)
229 /* We probably need to do more here but for now we just do
230 * the opposite of what NdisCompleteBindAdapter does
233 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)UnbindAdapterContext
;
235 if (!NT_SUCCESS(Status
)) {
236 NDIS_DbgPrint(MIN_TRACE
, ("Unbinding failed (%x)\n", Status
));
240 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
246 PLOGICAL_ADAPTER Adapter
,
249 * FUNCTION: Indicates a packet to bound protocols
251 * Adapter = Pointer to logical adapter
252 * Packet = Pointer to packet to indicate
254 * STATUS_SUCCESS in all cases
256 * - XXX ATM, this only handles loopback packets - is that its designed function?
262 PUCHAR LookaheadBuffer
;
264 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
267 MiniDisplayPacket(Packet
);
270 LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->NdisMiniportBlock
.CurrentLookahead
+ Adapter
->MediumHeaderSize
);
271 if (!LookaheadBuffer
) {
272 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
273 return NDIS_STATUS_RESOURCES
;
276 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
278 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
279 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
281 BufferedLength
= CopyPacketToBuffer(LookaheadBuffer
, Packet
, 0, Adapter
->NdisMiniportBlock
.CurrentLookahead
+
282 Adapter
->MediumHeaderSize
);
283 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = Packet
;
285 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
287 if (BufferedLength
> Adapter
->MediumHeaderSize
)
289 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
290 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
,
291 &LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
292 PacketLength
- Adapter
->MediumHeaderSize
);
296 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
299 ExFreePool(LookaheadBuffer
);
301 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
303 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = NULL
;
305 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
307 return NDIS_STATUS_SUCCESS
;
313 IN NDIS_HANDLE MacBindingHandle
,
314 IN PNDIS_REQUEST NdisRequest
)
316 * FUNCTION: Forwards a request to an NDIS miniport
318 * MacBindingHandle = Adapter binding handle
319 * NdisRequest = Pointer to request to perform
321 * Status of operation
324 PADAPTER_BINDING AdapterBinding
;
325 PLOGICAL_ADAPTER Adapter
;
326 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
328 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
330 ASSERT(MacBindingHandle
);
331 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
333 ASSERT(AdapterBinding
->Adapter
);
334 Adapter
= AdapterBinding
->Adapter
;
336 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
339 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
340 return NDIS_STATUS_PENDING
;
342 if (MiniIsBusy(Adapter
, NdisWorkItemRequest
)) {
343 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
344 return NDIS_STATUS_PENDING
;
347 return MiniDoRequest(Adapter
, NdisRequest
);
354 IN NDIS_HANDLE MacBindingHandle
)
356 PADAPTER_BINDING AdapterBinding
= MacBindingHandle
;
358 /* FIXME: Wait for all packets to be sent */
360 return MiniReset(AdapterBinding
->Adapter
);
364 ScatterGatherSendPacket(
365 IN PDEVICE_OBJECT DeviceObject
,
367 IN PSCATTER_GATHER_LIST ScatterGather
,
370 PDMA_CONTEXT DmaContext
= Context
;
371 PLOGICAL_ADAPTER Adapter
= DmaContext
->Adapter
;
372 PNDIS_PACKET Packet
= DmaContext
->Packet
;
375 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
377 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet
,
378 ScatterGatherListPacketInfo
) = ScatterGather
;
380 Status
= proSendPacketToMiniport(Adapter
, Packet
);
382 if (Status
!= NDIS_STATUS_PENDING
) {
383 NDIS_DbgPrint(MAX_TRACE
, ("Completing packet.\n"));
384 MiniSendComplete(Adapter
,
389 ExFreePool(DmaContext
);
393 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter
, PNDIS_PACKET Packet
)
396 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
397 return NDIS_STATUS_PENDING
;
400 NDIS_STATUS NdisStatus
;
402 if(MiniIsBusy(Adapter
, NdisWorkItemSend
)) {
403 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
404 return NDIS_STATUS_PENDING
;
407 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
409 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
411 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
412 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
413 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
414 NdisStatus
= NDIS_STATUS_PENDING
;
416 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
417 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
419 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
420 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
421 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
423 KeLowerIrql(RaiseOldIrql
);
425 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
426 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
427 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
428 NdisStatus
= NDIS_STATUS_PENDING
;
434 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
436 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
437 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
438 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
439 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
441 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
442 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
443 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
444 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
445 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
446 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
447 KeLowerIrql(RaiseOldIrql
);
449 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
450 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
451 NdisStatus
= NDIS_STATUS_PENDING
;
463 IN NDIS_HANDLE MacBindingHandle
,
464 IN PNDIS_PACKET Packet
)
466 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
468 * MacBindingHandle = Adapter binding handle
469 * Packet = Pointer to NDIS packet descriptor
471 * NDIS_STATUS_SUCCESS if the packet was successfully sent
472 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
475 PADAPTER_BINDING AdapterBinding
;
476 PLOGICAL_ADAPTER Adapter
;
477 PNDIS_BUFFER NdisBuffer
;
478 PDMA_CONTEXT Context
;
479 NDIS_STATUS NdisStatus
;
483 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
485 ASSERT(MacBindingHandle
);
486 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
488 ASSERT(AdapterBinding
);
489 Adapter
= AdapterBinding
->Adapter
;
493 /* if the following is not true, KeRaiseIrql() below will break */
494 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
496 /* XXX what is this crazy black magic? */
497 Packet
->Reserved
[1] = (ULONG_PTR
)MacBindingHandle
;
500 * Test the packet to see if it is a MAC loopback.
502 * We may have to loop this packet if miniport cannot.
503 * If dest MAC address of packet == MAC address of adapter,
504 * this is a loopback frame.
507 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
508 MiniAdapterHasAddress(Adapter
, Packet
))
511 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, Packet
, FALSE
);
512 return NDIS_STATUS_PENDING
;
514 return ProIndicatePacket(Adapter
, Packet
);
517 if (Adapter
->NdisMiniportBlock
.ScatterGatherListSize
!= 0)
519 NDIS_DbgPrint(MID_TRACE
, ("Using Scatter/Gather DMA\n"));
521 NdisQueryPacket(Packet
,
527 Context
= ExAllocatePool(NonPagedPool
, sizeof(DMA_CONTEXT
));
529 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
530 return NDIS_STATUS_RESOURCES
;
533 Context
->Adapter
= Adapter
;
534 Context
->Packet
= Packet
;
536 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
538 KeFlushIoBuffers(NdisBuffer
, FALSE
, TRUE
);
540 NdisStatus
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->GetScatterGatherList(
541 Adapter
->NdisMiniportBlock
.SystemAdapterObject
,
542 Adapter
->NdisMiniportBlock
.PhysicalDeviceObject
,
544 MmGetMdlVirtualAddress(NdisBuffer
),
546 ScatterGatherSendPacket
,
550 KeLowerIrql(OldIrql
);
552 if (!NT_SUCCESS(NdisStatus
)) {
553 NDIS_DbgPrint(MIN_TRACE
, ("GetScatterGatherList failed! (%x)\n", NdisStatus
));
557 return NDIS_STATUS_PENDING
;
561 return proSendPacketToMiniport(Adapter
, Packet
);
568 IN NDIS_HANDLE NdisBindingHandle
,
569 IN PPNDIS_PACKET PacketArray
,
570 IN UINT NumberOfPackets
)
572 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
573 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
575 NDIS_STATUS NdisStatus
;
578 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
580 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
582 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
583 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
587 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
588 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
589 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
590 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
591 KeLowerIrql(RaiseOldIrql
);
592 for (i
= 0; i
< NumberOfPackets
; i
++)
594 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
595 if (NdisStatus
!= NDIS_STATUS_PENDING
)
596 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
602 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
604 for (i
= 0; i
< NumberOfPackets
; i
++)
606 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
607 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
608 if (NdisStatus
!= NDIS_STATUS_PENDING
)
609 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
614 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
615 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
616 for (i
= 0; i
< NumberOfPackets
; i
++)
618 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
619 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
620 if (NdisStatus
!= NDIS_STATUS_PENDING
)
621 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
623 KeLowerIrql(RaiseOldIrql
);
631 IN NDIS_HANDLE MacBindingHandle
,
632 IN NDIS_HANDLE MacReceiveContext
,
634 IN UINT BytesToTransfer
,
635 IN OUT PNDIS_PACKET Packet
,
636 OUT PUINT BytesTransferred
)
638 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
640 * MacBindingHandle = Adapter binding handle
641 * MacReceiveContext = MAC receive context
642 * ByteOffset = Offset in packet to place data
643 * BytesToTransfer = Number of bytes to copy into packet
644 * Packet = Pointer to NDIS packet descriptor
645 * BytesTransferred = Address of buffer to place number of bytes copied
648 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
649 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
653 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
655 /* FIXME: Interrupts must be disabled for adapter */
656 /* XXX sd - why is that true? */
658 if (Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
659 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
660 /* NDIS is responsible for looping this packet */
661 NdisCopyFromPacketToPacket(Packet
,
662 ByteOffset
+ Adapter
->MediumHeaderSize
,
663 BytesToTransfer
+ Adapter
->MediumHeaderSize
,
664 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
667 return NDIS_STATUS_SUCCESS
;
670 ASSERT(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
);
672 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
674 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
677 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
682 KeLowerIrql(OldIrql
);
695 OUT PNDIS_STATUS Status
,
696 IN NDIS_HANDLE NdisBindingHandle
)
698 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
700 * Status = Address of buffer for status information
701 * NdisBindingHandle = Handle returned by NdisOpenAdapter
704 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
706 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
708 /* Remove from protocol's bound adapters list */
709 ExInterlockedRemoveEntryList(&AdapterBinding
->ProtocolListEntry
, &AdapterBinding
->ProtocolBinding
->Lock
);
711 /* Remove protocol from adapter's bound protocols list */
712 ExInterlockedRemoveEntryList(&AdapterBinding
->AdapterListEntry
, &AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
);
714 ExFreePool(AdapterBinding
);
716 *Status
= NDIS_STATUS_SUCCESS
;
725 NdisDeregisterProtocol(
726 OUT PNDIS_STATUS Status
,
727 IN NDIS_HANDLE NdisProtocolHandle
)
729 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
731 * Status = Address of buffer for status information
732 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
735 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
737 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
739 /* FIXME: Make sure no adapter bindings exist */
741 /* Remove protocol from global list */
742 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
744 ExFreePool(Protocol
);
746 *Status
= NDIS_STATUS_SUCCESS
;
756 OUT PNDIS_STATUS Status
,
757 OUT PNDIS_STATUS OpenErrorStatus
,
758 OUT PNDIS_HANDLE NdisBindingHandle
,
759 OUT PUINT SelectedMediumIndex
,
760 IN PNDIS_MEDIUM MediumArray
,
761 IN UINT MediumArraySize
,
762 IN NDIS_HANDLE NdisProtocolHandle
,
763 IN NDIS_HANDLE ProtocolBindingContext
,
764 IN PNDIS_STRING AdapterName
,
766 IN PSTRING AddressingInformation OPTIONAL
)
768 * FUNCTION: Opens an adapter for communication
770 * Status = Address of buffer for status information
771 * OpenErrorStatus = Address of buffer for secondary error code
772 * NdisBindingHandle = Address of buffer for adapter binding handle
773 * SelectedMediumIndex = Address of buffer for selected medium
774 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
775 * MediumArraySize = Number of elements in MediumArray
776 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
777 * ProtocolBindingContext = Pointer to caller suplied context area
778 * AdapterName = Pointer to buffer with name of adapter
779 * OpenOptions = Bitmask with flags passed to next-lower driver
780 * AddressingInformation = Optional pointer to buffer with NIC specific information
785 PLOGICAL_ADAPTER Adapter
;
786 PADAPTER_BINDING AdapterBinding
;
787 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
789 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
791 if(!NdisProtocolHandle
)
793 NDIS_DbgPrint(MIN_TRACE
, ("NdisProtocolHandle is NULL\n"));
794 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
798 Adapter
= MiniLocateDevice(AdapterName
);
801 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
802 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
806 /* Find the media type in the list provided by the protocol driver */
808 for (i
= 0; i
< MediumArraySize
; i
++)
810 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
812 *SelectedMediumIndex
= i
;
820 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
821 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
825 /* Now that we have confirmed that the adapter can be opened, create a binding */
827 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
830 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
831 *Status
= NDIS_STATUS_RESOURCES
;
835 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
837 AdapterBinding
->ProtocolBinding
= Protocol
;
838 AdapterBinding
->Adapter
= Adapter
;
839 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
841 /* Set fields required by some NDIS macros */
842 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
844 /* Set handlers (some NDIS macros require these) */
846 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
847 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
848 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
849 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
850 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
852 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
853 Protocol
->Chars
.RequestCompleteHandler
;
855 /* Put on protocol's bound adapters list */
856 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
858 /* Put protocol on adapter's bound protocols list */
859 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
860 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
862 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
864 *Status
= NDIS_STATUS_SUCCESS
;
869 LocateAdapterBindingByName(IN PPROTOCOL_BINDING ProtocolBinding
, IN PNDIS_STRING AdapterName
)
871 PLIST_ENTRY CurrentEntry
;
872 PADAPTER_BINDING AdapterBinding
;
875 KeAcquireSpinLock(&ProtocolBinding
->Lock
, &OldIrql
);
877 CurrentEntry
= ProtocolBinding
->AdapterListHead
.Flink
;
879 while (CurrentEntry
!= &ProtocolBinding
->AdapterListHead
)
881 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, ProtocolListEntry
);
883 if (RtlCompareUnicodeString(AdapterName
, &AdapterBinding
->Adapter
->NdisMiniportBlock
.MiniportName
, TRUE
) == 0)
885 KeReleaseSpinLock(&ProtocolBinding
->Lock
, OldIrql
);
886 return AdapterBinding
;
889 CurrentEntry
= CurrentEntry
->Flink
;
892 KeReleaseSpinLock(&ProtocolBinding
->Lock
, OldIrql
);
899 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status
, IN PPROTOCOL_BINDING Protocol
)
902 * bind the protocol to all of its miniports
905 * get list of devices from Bind key
906 * call BindAdapterHandler for each
908 OBJECT_ATTRIBUTES ObjectAttributes
;
909 UNICODE_STRING RegistryPath
;
910 WCHAR
*RegistryPathStr
, *DataPtr
= NULL
;
912 HANDLE DriverKeyHandle
= NULL
;
913 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
914 PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
= &Protocol
->Chars
;
915 UNICODE_STRING ValueName
;
917 PLIST_ENTRY CurrentEntry
= NULL
;
919 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
922 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
923 *Status
= NDIS_STATUS_RESOURCES
;
927 wcscpy(RegistryPathStr
, SERVICES_KEY
);
928 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
929 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
930 wcscat(RegistryPathStr
, LINKAGE_KEY
);
932 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
933 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
935 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
936 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
938 ExFreePool(RegistryPathStr
);
940 if(NT_SUCCESS(NtStatus
))
942 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
944 RtlInitUnicodeString(&ValueName
, L
"Bind");
946 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
947 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
949 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value for size\n"));
950 ZwClose(DriverKeyHandle
);
954 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
957 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
958 ZwClose(DriverKeyHandle
);
959 NtStatus
= STATUS_NO_MEMORY
;
963 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
964 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
966 ZwClose(DriverKeyHandle
);
968 if(!NT_SUCCESS(NtStatus
))
970 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
971 ExFreePool(KeyInformation
);
972 KeyInformation
= NULL
;
978 if (!NT_SUCCESS(NtStatus
))
980 NDIS_DbgPrint(MIN_TRACE
, ("Performing global bind for protocol '%wZ'\n", &ProtocolCharacteristics
->Name
));
981 KeyInformation
= NULL
;
983 CurrentEntry
= AdapterListHead
.Flink
;
987 NDIS_DbgPrint(MIN_TRACE
, ("Performing standard bind for protocol '%wZ'\n", &ProtocolCharacteristics
->Name
));
989 DataPtr
= (WCHAR
*)KeyInformation
->Data
;
992 /* Assume success for now */
993 *Status
= NDIS_STATUS_SUCCESS
;
997 /* BindContext is for tracking pending binding operations */
998 VOID
*BindContext
= 0;
999 NDIS_STRING DeviceName
;
1000 NDIS_STRING RegistryPath
;
1001 WCHAR
*RegistryPathStr
= NULL
;
1002 ULONG PathLength
= 0;
1003 PLOGICAL_ADAPTER Adapter
;
1007 /* Parse the REG_MULTI_SZ entry for device names */
1011 RtlInitUnicodeString(&DeviceName
, DataPtr
);
1015 /* Use the device name from the global adapter list */
1016 if (CurrentEntry
== &AdapterListHead
)
1019 Adapter
= CONTAINING_RECORD(CurrentEntry
, LOGICAL_ADAPTER
, ListEntry
);
1021 DeviceName
= Adapter
->NdisMiniportBlock
.MiniportName
;
1024 /* Make sure the adapter has started */
1025 if (!MiniLocateDevice(&DeviceName
))
1027 /* It wasn't in the global miniport list, so skip the bind entry */
1031 /* Make sure this device isn't already bound to this protocol */
1032 if (LocateAdapterBindingByName(Protocol
, &DeviceName
))
1034 /* It was already in this protocol's bound adapter list, so skip the bind entry */
1039 * RegistryPath should be:
1040 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
1042 * This is constructed as follows:
1043 * SERVICES_KEY + extracted device name + Protocol name from characteristics
1046 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
1047 wcslen( DeviceName
.Buffer
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
1048 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
1049 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
1051 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
1052 if(!RegistryPathStr
)
1054 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
1055 *Status
= NDIS_STATUS_RESOURCES
;
1059 wcscpy(RegistryPathStr
, SERVICES_KEY
);
1060 wcscat(RegistryPathStr
, DeviceName
.Buffer
+ 8 );
1061 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
1062 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
1064 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
1066 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
1068 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
1069 &DeviceName
, &RegistryPath
));
1072 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
1075 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
1076 NDIS_DbgPrint(MIN_TRACE
, ("%wZ's BindAdapter handler returned 0x%x for %wZ\n", &ProtocolCharacteristics
->Name
, *Status
, &DeviceName
));
1079 NDIS_DbgPrint(MIN_TRACE
, ("No protocol bind handler specified\n"));
1085 /* Advance to the next adapter in the REG_MULTI_SZ */
1086 DataPtr
+= (DeviceName
.Length
/ sizeof(WCHAR
)) + 1;
1090 /* Advance to the next adapter in the global list */
1091 CurrentEntry
= CurrentEntry
->Flink
;
1097 ExFreePool(KeyInformation
);
1106 NdisRegisterProtocol(
1107 OUT PNDIS_STATUS Status
,
1108 OUT PNDIS_HANDLE NdisProtocolHandle
,
1109 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
1110 IN UINT CharacteristicsLength
)
1112 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
1114 * Status = Address of buffer for status information
1115 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
1116 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
1117 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
1119 * - you *must* set NdisProtocolHandle before doing anything that could wind up
1120 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
1121 * - the above implies that the initialization of the protocol block must be complete
1124 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
1125 * - make this thing able to handle >1 protocol
1128 PPROTOCOL_BINDING Protocol
;
1131 PNET_PNP_EVENT PnPEvent
;
1133 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
1135 *NdisProtocolHandle
= NULL
;
1137 /* first validate the PROTOCOL_CHARACTERISTICS */
1138 switch (ProtocolCharacteristics
->MajorNdisVersion
)
1141 /* we don't really want to support ndis3 drivers - so we complain for now */
1142 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
1143 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
1147 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
1151 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
1155 *Status
= NDIS_STATUS_BAD_VERSION
;
1156 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
1160 if (CharacteristicsLength
< MinSize
)
1162 NDIS_DbgPrint(MIN_TRACE
, ("Bad protocol characteristics.\n"));
1163 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
1167 /* set up the protocol block */
1168 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
1171 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1172 *Status
= NDIS_STATUS_RESOURCES
;
1176 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
1177 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
1179 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
1180 if (!NT_SUCCESS(NtStatus
))
1182 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1183 ExFreePool(Protocol
);
1184 *Status
= NDIS_STATUS_RESOURCES
;
1188 KeInitializeSpinLock(&Protocol
->Lock
);
1190 InitializeListHead(&Protocol
->AdapterListHead
);
1192 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
1193 * BindAdapter handler might need it */
1195 *NdisProtocolHandle
= Protocol
;
1197 ndisBindMiniportsToProtocol(Status
, Protocol
);
1199 /* Should we only send this if ndisBindMiniportsToProtocol succeeds? */
1200 PnPEvent
= ProSetupPnPEvent(NetEventBindsComplete
, NULL
, 0);
1203 if (Protocol
->Chars
.PnPEventHandler
)
1205 /* We call this with a NULL binding context because it affects all bindings */
1206 NtStatus
= (*Protocol
->Chars
.PnPEventHandler
)(NULL
,
1209 /* FIXME: We don't support this yet */
1210 ASSERT(NtStatus
!= NDIS_STATUS_PENDING
);
1213 ExFreePool(PnPEvent
);
1216 if (*Status
== NDIS_STATUS_SUCCESS
) {
1217 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
1219 NDIS_DbgPrint(MIN_TRACE
, ("Binding failed (%x)\n", *Status
));
1220 ExFreePool(Protocol
);
1221 *NdisProtocolHandle
= NULL
;
1232 OUT PNDIS_STATUS Status
,
1233 IN NDIS_HANDLE NdisBindingHandle
,
1234 IN PNDIS_REQUEST NdisRequest
)
1236 * FUNCTION: Forwards a request to an NDIS driver
1238 * Status = Address of buffer for status information
1239 * NdisBindingHandle = Adapter binding handle
1240 * NdisRequest = Pointer to request to perform
1243 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
1253 OUT PNDIS_STATUS Status
,
1254 IN NDIS_HANDLE NdisBindingHandle
)
1256 *Status
= ProReset(NdisBindingHandle
);
1267 OUT PNDIS_STATUS Status
,
1268 IN NDIS_HANDLE NdisBindingHandle
,
1269 IN PNDIS_PACKET Packet
)
1271 * FUNCTION: Forwards a request to send a packet
1273 * Status = Address of buffer for status information
1274 * NdisBindingHandle = Adapter binding handle
1275 * Packet = Pointer to NDIS packet descriptor
1278 *Status
= ProSend(NdisBindingHandle
, Packet
);
1285 #undef NdisSendPackets
1289 IN NDIS_HANDLE NdisBindingHandle
,
1290 IN PPNDIS_PACKET PacketArray
,
1291 IN UINT NumberOfPackets
)
1293 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
1300 #undef NdisTransferData
1304 OUT PNDIS_STATUS Status
,
1305 IN NDIS_HANDLE NdisBindingHandle
,
1306 IN NDIS_HANDLE MacReceiveContext
,
1308 IN UINT BytesToTransfer
,
1309 IN OUT PNDIS_PACKET Packet
,
1310 OUT PUINT BytesTransferred
)
1312 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1314 * Status = Address of buffer for status information
1315 * NdisBindingHandle = Adapter binding handle
1316 * MacReceiveContext = MAC receive context
1317 * ByteOffset = Offset in packet to place data
1318 * BytesToTransfer = Number of bytes to copy into packet
1319 * Packet = Pointer to NDIS packet descriptor
1320 * BytesTransferred = Address of buffer to place number of bytes copied
1323 *Status
= ProTransferData(NdisBindingHandle
,
1336 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle
)
1338 NDIS_STATUS NdisStatus
;
1340 ndisBindMiniportsToProtocol(&NdisStatus
, NdisProtocolHandle
);
1349 NdisGetDriverHandle(
1350 IN PNDIS_HANDLE NdisBindingHandle
,
1351 OUT PNDIS_HANDLE NdisDriverHandle
)
1359 PADAPTER_BINDING Binding
= (PADAPTER_BINDING
)NdisBindingHandle
;
1363 NDIS_DbgPrint(MIN_TRACE
, ("Bad binding handle\n"));
1364 *NdisDriverHandle
= NULL
;
1368 *NdisDriverHandle
= Binding
->Adapter
->NdisMiniportBlock
.DriverHandle
;