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
16 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
17 #define LINKAGE_KEY L"\\Linkage"
18 #define PARAMETERS_KEY L"\\Parameters\\"
20 LIST_ENTRY ProtocolListHead
;
21 KSPIN_LOCK ProtocolListLock
;
27 NET_PNP_EVENT_CODE EventCode
,
29 ULONG EventBufferLength
)
31 PNET_PNP_EVENT PnPEvent
;
33 PnPEvent
= ExAllocatePool(PagedPool
, sizeof(NET_PNP_EVENT
));
37 RtlZeroMemory(PnPEvent
, sizeof(NET_PNP_EVENT
));
39 PnPEvent
->NetEvent
= EventCode
;
40 PnPEvent
->Buffer
= EventBuffer
;
41 PnPEvent
->BufferLength
= EventBufferLength
;
48 NdisIPnPQueryStopDevice(
49 IN PDEVICE_OBJECT DeviceObject
,
52 PLIST_ENTRY CurrentEntry
;
53 PADAPTER_BINDING AdapterBinding
;
54 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
55 PNET_PNP_EVENT PnPEvent
;
58 PnPEvent
= ProSetupPnPEvent(NetEventQueryRemoveDevice
, NULL
, 0);
60 return NDIS_STATUS_RESOURCES
;
62 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
64 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
66 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
68 Status
= (*AdapterBinding
->ProtocolBinding
->Chars
.PnPEventHandler
)(
69 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
72 if (Status
== NDIS_STATUS_PENDING
)
74 /* We don't handle this yet */
77 else if (Status
!= NDIS_STATUS_SUCCESS
)
79 /* One protocol failed so we can fail the query stop device IRP */
84 CurrentEntry
= CurrentEntry
->Flink
;
89 return NDIS_STATUS_SUCCESS
;
94 NdisIPnPCancelStopDevice(
95 IN PDEVICE_OBJECT DeviceObject
,
98 PLIST_ENTRY CurrentEntry
;
99 PADAPTER_BINDING AdapterBinding
;
100 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)DeviceObject
->DeviceExtension
;
101 PNET_PNP_EVENT PnPEvent
;
104 PnPEvent
= ProSetupPnPEvent(NetEventCancelRemoveDevice
, NULL
, 0);
106 return NDIS_STATUS_RESOURCES
;
108 CurrentEntry
= Adapter
->ProtocolListHead
.Flink
;
110 while (CurrentEntry
!= &Adapter
->ProtocolListHead
)
112 AdapterBinding
= CONTAINING_RECORD(CurrentEntry
, ADAPTER_BINDING
, AdapterListEntry
);
114 Status
= (*AdapterBinding
->ProtocolBinding
->Chars
.PnPEventHandler
)(
115 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
,
118 /* A protocol should always succeed NetEventCancelRemoveDevice */
120 ASSERT(Status
== NDIS_STATUS_SUCCESS
);
122 CurrentEntry
= CurrentEntry
->Flink
;
125 ExFreePool(PnPEvent
);
127 return NDIS_STATUS_SUCCESS
;
136 NdisCompleteBindAdapter(
137 IN NDIS_HANDLE BindAdapterContext
,
138 IN NDIS_STATUS Status
,
139 IN NDIS_STATUS OpenStatus
)
141 * FUNCTION: Indicates a packet to bound protocols
143 * Adapter = Pointer to logical adapter
144 * Packet = Pointer to packet to indicate
146 * Status of operation
148 * - FIXME: partially-implemented
151 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)BindAdapterContext
;
153 if (!NT_SUCCESS(Status
)) return;
155 /* Put protocol binding struct on global list */
156 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
164 NdisCompleteUnbindAdapter(
165 IN NDIS_HANDLE UnbindAdapterContext
,
166 IN NDIS_STATUS Status
)
168 /* We probably need to do more here but for now we just do
169 * the opposite of what NdisCompleteBindAdapter does
172 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)UnbindAdapterContext
;
174 if (!NT_SUCCESS(Status
)) return;
176 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
182 PLOGICAL_ADAPTER Adapter
,
185 * FUNCTION: Indicates a packet to bound protocols
187 * Adapter = Pointer to logical adapter
188 * Packet = Pointer to packet to indicate
190 * STATUS_SUCCESS in all cases
192 * - XXX ATM, this only handles loopback packets - is that its designed function?
198 PUCHAR LookaheadBuffer
;
200 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
203 MiniDisplayPacket(Packet
);
206 LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->NdisMiniportBlock
.CurrentLookahead
+ Adapter
->MediumHeaderSize
);
207 if (!LookaheadBuffer
)
208 return NDIS_STATUS_RESOURCES
;
210 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
212 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
213 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
215 BufferedLength
= CopyPacketToBuffer(LookaheadBuffer
, Packet
, 0, Adapter
->NdisMiniportBlock
.CurrentLookahead
);
217 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
219 if (BufferedLength
> Adapter
->MediumHeaderSize
)
221 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
222 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
,
223 &LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
224 PacketLength
- Adapter
->MediumHeaderSize
);
228 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
231 ExFreePool(LookaheadBuffer
);
233 return NDIS_STATUS_SUCCESS
;
239 IN NDIS_HANDLE MacBindingHandle
,
240 IN PNDIS_REQUEST NdisRequest
)
242 * FUNCTION: Forwards a request to an NDIS miniport
244 * MacBindingHandle = Adapter binding handle
245 * NdisRequest = Pointer to request to perform
247 * Status of operation
250 PADAPTER_BINDING AdapterBinding
;
251 PLOGICAL_ADAPTER Adapter
;
252 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
254 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
256 ASSERT(MacBindingHandle
);
257 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
259 ASSERT(AdapterBinding
->Adapter
);
260 Adapter
= AdapterBinding
->Adapter
;
262 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
265 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
266 return NDIS_STATUS_PENDING
;
268 if (MiniIsBusy(Adapter
, NdisWorkItemRequest
)) {
269 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
270 return NDIS_STATUS_PENDING
;
273 return MiniDoRequest(Adapter
, NdisRequest
);
280 IN NDIS_HANDLE MacBindingHandle
)
284 return NDIS_STATUS_FAILURE
;
288 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter
, PNDIS_PACKET Packet
)
291 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
292 return NDIS_STATUS_PENDING
;
295 NDIS_STATUS NdisStatus
;
297 if(MiniIsBusy(Adapter
, NdisWorkItemSend
)) {
298 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
299 return NDIS_STATUS_PENDING
;
302 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
304 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
306 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
307 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
308 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
309 NdisStatus
= NDIS_STATUS_PENDING
;
311 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
312 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
314 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
315 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
316 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
318 KeLowerIrql(RaiseOldIrql
);
320 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
321 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
322 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
323 NdisStatus
= NDIS_STATUS_PENDING
;
329 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
331 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
332 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
333 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
334 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
336 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
337 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
338 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
339 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
340 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
341 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
342 KeLowerIrql(RaiseOldIrql
);
344 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
345 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
346 NdisStatus
= NDIS_STATUS_PENDING
;
358 IN NDIS_HANDLE MacBindingHandle
,
359 IN PNDIS_PACKET Packet
)
361 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
363 * MacBindingHandle = Adapter binding handle
364 * Packet = Pointer to NDIS packet descriptor
366 * NDIS_STATUS_SUCCESS if the packet was successfully sent
367 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
370 PADAPTER_BINDING AdapterBinding
;
371 PLOGICAL_ADAPTER Adapter
;
373 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
375 ASSERT(MacBindingHandle
);
376 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
378 ASSERT(AdapterBinding
);
379 Adapter
= AdapterBinding
->Adapter
;
383 /* if the following is not true, KeRaiseIrql() below will break */
384 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
386 /* XXX what is this crazy black magic? */
387 Packet
->Reserved
[1] = (ULONG_PTR
)MacBindingHandle
;
390 * Test the packet to see if it is a MAC loopback.
392 * We may have to loop this packet if miniport cannot.
393 * If dest MAC address of packet == MAC address of adapter,
394 * this is a loopback frame.
397 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
398 MiniAdapterHasAddress(Adapter
, Packet
))
401 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, Packet
, FALSE
);
402 return NDIS_STATUS_PENDING
;
404 return ProIndicatePacket(Adapter
, Packet
);
407 return proSendPacketToMiniport(Adapter
, Packet
);
414 IN NDIS_HANDLE NdisBindingHandle
,
415 IN PPNDIS_PACKET PacketArray
,
416 IN UINT NumberOfPackets
)
418 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
419 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
421 NDIS_STATUS NdisStatus
;
424 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
426 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
428 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
429 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
433 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
434 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
435 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
436 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
437 KeLowerIrql(RaiseOldIrql
);
438 for (i
= 0; i
< NumberOfPackets
; i
++)
440 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
441 if (NdisStatus
!= NDIS_STATUS_PENDING
)
442 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
448 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
450 for (i
= 0; i
< NumberOfPackets
; i
++)
452 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
453 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
454 if (NdisStatus
!= NDIS_STATUS_PENDING
)
455 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
460 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
461 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
462 for (i
= 0; i
< NumberOfPackets
; i
++)
464 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
465 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
466 if (NdisStatus
!= NDIS_STATUS_PENDING
)
467 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
469 KeLowerIrql(RaiseOldIrql
);
477 IN NDIS_HANDLE MacBindingHandle
,
478 IN NDIS_HANDLE MacReceiveContext
,
480 IN UINT BytesToTransfer
,
481 IN OUT PNDIS_PACKET Packet
,
482 OUT PUINT BytesTransferred
)
484 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
486 * MacBindingHandle = Adapter binding handle
487 * MacReceiveContext = MAC receive context
488 * ByteOffset = Offset in packet to place data
489 * BytesToTransfer = Number of bytes to copy into packet
490 * Packet = Pointer to NDIS packet descriptor
491 * BytesTransferred = Address of buffer to place number of bytes copied
494 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
495 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
499 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
501 /* FIXME: Interrupts must be disabled for adapter */
502 /* XXX sd - why is that true? */
504 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
505 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
506 /* NDIS is responsible for looping this packet */
507 NdisCopyFromPacketToPacket(Packet
,
510 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
513 return NDIS_STATUS_SUCCESS
;
516 ASSERT(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
);
518 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
520 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
523 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
528 KeLowerIrql(OldIrql
);
541 OUT PNDIS_STATUS Status
,
542 IN NDIS_HANDLE NdisBindingHandle
)
544 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
546 * Status = Address of buffer for status information
547 * NdisBindingHandle = Handle returned by NdisOpenAdapter
550 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
552 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
554 /* Remove from protocol's bound adapters list */
555 ExInterlockedRemoveEntryList(&AdapterBinding
->ProtocolListEntry
, &AdapterBinding
->ProtocolBinding
->Lock
);
557 /* Remove protocol from adapter's bound protocols list */
558 ExInterlockedRemoveEntryList(&AdapterBinding
->AdapterListEntry
, &AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
);
560 ExFreePool(AdapterBinding
);
562 *Status
= NDIS_STATUS_SUCCESS
;
571 NdisDeregisterProtocol(
572 OUT PNDIS_STATUS Status
,
573 IN NDIS_HANDLE NdisProtocolHandle
)
575 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
577 * Status = Address of buffer for status information
578 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
581 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
583 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
585 /* FIXME: Make sure no adapter bindings exist */
587 /* Remove protocol from global list */
588 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
590 ExFreePool(Protocol
);
592 *Status
= NDIS_STATUS_SUCCESS
;
602 OUT PNDIS_STATUS Status
,
603 OUT PNDIS_STATUS OpenErrorStatus
,
604 OUT PNDIS_HANDLE NdisBindingHandle
,
605 OUT PUINT SelectedMediumIndex
,
606 IN PNDIS_MEDIUM MediumArray
,
607 IN UINT MediumArraySize
,
608 IN NDIS_HANDLE NdisProtocolHandle
,
609 IN NDIS_HANDLE ProtocolBindingContext
,
610 IN PNDIS_STRING AdapterName
,
612 IN PSTRING AddressingInformation OPTIONAL
)
614 * FUNCTION: Opens an adapter for communication
616 * Status = Address of buffer for status information
617 * OpenErrorStatus = Address of buffer for secondary error code
618 * NdisBindingHandle = Address of buffer for adapter binding handle
619 * SelectedMediumIndex = Address of buffer for selected medium
620 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
621 * MediumArraySize = Number of elements in MediumArray
622 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
623 * ProtocolBindingContext = Pointer to caller suplied context area
624 * AdapterName = Pointer to buffer with name of adapter
625 * OpenOptions = Bitmask with flags passed to next-lower driver
626 * AddressingInformation = Optional pointer to buffer with NIC specific information
631 PLOGICAL_ADAPTER Adapter
;
632 PADAPTER_BINDING AdapterBinding
;
633 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
635 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
637 if(!NdisProtocolHandle
)
639 NDIS_DbgPrint(MAX_TRACE
, ("NdisProtocolHandle is NULL\n"));
640 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
644 Adapter
= MiniLocateDevice(AdapterName
);
647 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
648 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
652 /* Find the media type in the list provided by the protocol driver */
654 for (i
= 0; i
< MediumArraySize
; i
++)
656 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
658 *SelectedMediumIndex
= i
;
666 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
667 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
671 /* Now that we have confirmed that the adapter can be opened, create a binding */
673 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
676 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
677 *Status
= NDIS_STATUS_RESOURCES
;
681 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
683 AdapterBinding
->ProtocolBinding
= Protocol
;
684 AdapterBinding
->Adapter
= Adapter
;
685 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
687 /* Set fields required by some NDIS macros */
688 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
690 /* Set handlers (some NDIS macros require these) */
692 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
693 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
694 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
695 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
696 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
698 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
699 Protocol
->Chars
.RequestCompleteHandler
;
701 /* Put on protocol's bound adapters list */
702 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
704 /* Put protocol on adapter's bound protocols list */
705 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
706 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
708 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
710 *Status
= NDIS_STATUS_SUCCESS
;
715 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status
, IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
)
718 * bind the protocol to all of its miniports
721 * get list of devices from Bind key
722 * call BindAdapterHandler for each
724 OBJECT_ATTRIBUTES ObjectAttributes
;
725 UNICODE_STRING RegistryPath
;
726 WCHAR
*RegistryPathStr
;
729 HANDLE DriverKeyHandle
= NULL
;
730 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
732 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
735 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
736 *Status
= NDIS_STATUS_RESOURCES
;
740 wcscpy(RegistryPathStr
, SERVICES_KEY
);
741 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
742 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
743 wcscat(RegistryPathStr
, LINKAGE_KEY
);
745 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
746 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
748 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
749 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
751 ExFreePool(RegistryPathStr
);
753 if(!NT_SUCCESS(NtStatus
))
755 NDIS_DbgPrint(MIN_TRACE
, ("Unable to open protocol configuration\n"));
756 *Status
= NDIS_STATUS_FAILURE
;
760 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
763 UNICODE_STRING ValueName
;
766 RtlInitUnicodeString(&ValueName
, L
"Bind");
768 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
769 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
771 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value for size\n"));
772 ZwClose(DriverKeyHandle
);
773 *Status
= NDIS_STATUS_FAILURE
;
777 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
780 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
781 ZwClose(DriverKeyHandle
);
782 *Status
= NDIS_STATUS_FAILURE
;
786 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
787 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
789 ZwClose(DriverKeyHandle
);
791 if(!NT_SUCCESS(NtStatus
))
793 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
794 ExFreePool(KeyInformation
);
795 *Status
= NDIS_STATUS_FAILURE
;
800 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
802 DataPtr
+= wcslen(DataPtr
) + 1)
804 /* BindContext is for tracking pending binding operations */
805 VOID
*BindContext
= 0;
806 NDIS_STRING DeviceName
;
807 NDIS_STRING RegistryPath
;
808 WCHAR
*RegistryPathStr
= NULL
;
809 ULONG PathLength
= 0;
811 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
814 * RegistryPath should be:
815 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
817 * This is constructed as follows:
818 * SERVICES_KEY + extracted device name + Protocol name from characteristics
821 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
822 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
823 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
824 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
826 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
829 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
830 ExFreePool(KeyInformation
);
831 *Status
= NDIS_STATUS_RESOURCES
;
835 wcscpy(RegistryPathStr
, SERVICES_KEY
);
836 wcscat(RegistryPathStr
, DataPtr
+ 8 );
837 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
838 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
840 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
842 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
844 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
845 &DeviceName
, &RegistryPath
));
848 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
850 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
852 NDIS_DbgPrint(MID_TRACE
, ("No protocol bind handler specified\n"));
856 *Status
= NDIS_STATUS_SUCCESS
;
857 ExFreePool(KeyInformation
);
865 NdisRegisterProtocol(
866 OUT PNDIS_STATUS Status
,
867 OUT PNDIS_HANDLE NdisProtocolHandle
,
868 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
869 IN UINT CharacteristicsLength
)
871 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
873 * Status = Address of buffer for status information
874 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
875 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
876 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
878 * - you *must* set NdisProtocolHandle before doing anything that could wind up
879 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
880 * - the above implies that the initialization of the protocol block must be complete
883 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
884 * - make this thing able to handle >1 protocol
887 PPROTOCOL_BINDING Protocol
;
891 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
893 *NdisProtocolHandle
= NULL
;
895 /* first validate the PROTOCOL_CHARACTERISTICS */
896 switch (ProtocolCharacteristics
->MajorNdisVersion
)
899 /* we don't really want to support ndis3 drivers - so we complain for now */
900 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
901 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
905 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
909 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
913 *Status
= NDIS_STATUS_BAD_VERSION
;
914 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
918 if (CharacteristicsLength
< MinSize
)
920 NDIS_DbgPrint(MIN_TRACE
, ("Bad protocol characteristics.\n"));
921 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
925 /* set up the protocol block */
926 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
929 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
930 *Status
= NDIS_STATUS_RESOURCES
;
934 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
935 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
937 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
938 if (!NT_SUCCESS(NtStatus
))
940 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
941 ExFreePool(Protocol
);
942 *Status
= NDIS_STATUS_RESOURCES
;
946 KeInitializeSpinLock(&Protocol
->Lock
);
948 InitializeListHead(&Protocol
->AdapterListHead
);
950 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
951 * BindAdapter handler might need it */
953 *NdisProtocolHandle
= Protocol
;
955 ndisBindMiniportsToProtocol(Status
, &Protocol
->Chars
);
957 if (*Status
== NDIS_STATUS_SUCCESS
) {
958 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
960 ExFreePool(Protocol
);
961 *NdisProtocolHandle
= NULL
;
972 OUT PNDIS_STATUS Status
,
973 IN NDIS_HANDLE NdisBindingHandle
,
974 IN PNDIS_REQUEST NdisRequest
)
976 * FUNCTION: Forwards a request to an NDIS driver
978 * Status = Address of buffer for status information
979 * NdisBindingHandle = Adapter binding handle
980 * NdisRequest = Pointer to request to perform
983 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
993 OUT PNDIS_STATUS Status
,
994 IN NDIS_HANDLE NdisBindingHandle
)
996 *Status
= ProReset(NdisBindingHandle
);
1007 OUT PNDIS_STATUS Status
,
1008 IN NDIS_HANDLE NdisBindingHandle
,
1009 IN PNDIS_PACKET Packet
)
1011 * FUNCTION: Forwards a request to send a packet
1013 * Status = Address of buffer for status information
1014 * NdisBindingHandle = Adapter binding handle
1015 * Packet = Pointer to NDIS packet descriptor
1018 *Status
= ProSend(NdisBindingHandle
, Packet
);
1025 #undef NdisSendPackets
1029 IN NDIS_HANDLE NdisBindingHandle
,
1030 IN PPNDIS_PACKET PacketArray
,
1031 IN UINT NumberOfPackets
)
1033 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
1040 #undef NdisTransferData
1044 OUT PNDIS_STATUS Status
,
1045 IN NDIS_HANDLE NdisBindingHandle
,
1046 IN NDIS_HANDLE MacReceiveContext
,
1048 IN UINT BytesToTransfer
,
1049 IN OUT PNDIS_PACKET Packet
,
1050 OUT PUINT BytesTransferred
)
1052 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
1054 * Status = Address of buffer for status information
1055 * NdisBindingHandle = Adapter binding handle
1056 * MacReceiveContext = MAC receive context
1057 * ByteOffset = Offset in packet to place data
1058 * BytesToTransfer = Number of bytes to copy into packet
1059 * Packet = Pointer to NDIS packet descriptor
1060 * BytesTransferred = Address of buffer to place number of bytes copied
1063 *Status
= ProTransferData(NdisBindingHandle
,
1076 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle
)
1078 PPROTOCOL_BINDING Protocol
= NdisProtocolHandle
;
1079 NDIS_STATUS NdisStatus
;
1081 ndisBindMiniportsToProtocol(&NdisStatus
, &Protocol
->Chars
);
1090 NdisGetDriverHandle(
1091 IN PNDIS_HANDLE NdisBindingHandle
,
1092 OUT PNDIS_HANDLE NdisDriverHandle
)
1100 PADAPTER_BINDING Binding
= (PADAPTER_BINDING
)NdisBindingHandle
;
1104 *NdisDriverHandle
= NULL
;
1108 *NdisDriverHandle
= Binding
->Adapter
->NdisMiniportBlock
.DriverHandle
;