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
;
31 NdisCompleteBindAdapter(
32 IN NDIS_HANDLE BindAdapterContext
,
33 IN NDIS_STATUS Status
,
34 IN NDIS_STATUS OpenStatus
)
36 * FUNCTION: Indicates a packet to bound protocols
38 * Adapter = Pointer to logical adapter
39 * Packet = Pointer to packet to indicate
43 * - FIXME: partially-implemented
46 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)BindAdapterContext
;
48 if (!NT_SUCCESS(Status
)) return;
50 /* Put protocol binding struct on global list */
51 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
59 NdisCompleteUnbindAdapter(
60 IN NDIS_HANDLE UnbindAdapterContext
,
61 IN NDIS_STATUS Status
)
63 /* We probably need to do more here but for now we just do
64 * the opposite of what NdisCompleteBindAdapter does
67 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)UnbindAdapterContext
;
69 if (!NT_SUCCESS(Status
)) return;
71 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
77 PLOGICAL_ADAPTER Adapter
,
80 * FUNCTION: Indicates a packet to bound protocols
82 * Adapter = Pointer to logical adapter
83 * Packet = Pointer to packet to indicate
85 * STATUS_SUCCESS in all cases
87 * - XXX ATM, this only handles loopback packets - is that its designed function?
93 PUCHAR LookaheadBuffer
;
95 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
98 MiniDisplayPacket(Packet
);
101 LookaheadBuffer
= ExAllocatePool(NonPagedPool
, Adapter
->NdisMiniportBlock
.CurrentLookahead
+ Adapter
->MediumHeaderSize
);
102 if (!LookaheadBuffer
)
103 return NDIS_STATUS_RESOURCES
;
105 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
107 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
108 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
110 BufferedLength
= CopyPacketToBuffer(LookaheadBuffer
, Packet
, 0, Adapter
->NdisMiniportBlock
.CurrentLookahead
);
112 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
114 if (BufferedLength
> Adapter
->MediumHeaderSize
)
116 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
117 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
,
118 &LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
119 PacketLength
- Adapter
->MediumHeaderSize
);
123 MiniIndicateData(Adapter
, NULL
, LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
126 ExFreePool(LookaheadBuffer
);
128 return NDIS_STATUS_SUCCESS
;
134 IN NDIS_HANDLE MacBindingHandle
,
135 IN PNDIS_REQUEST NdisRequest
)
137 * FUNCTION: Forwards a request to an NDIS miniport
139 * MacBindingHandle = Adapter binding handle
140 * NdisRequest = Pointer to request to perform
142 * Status of operation
145 PADAPTER_BINDING AdapterBinding
;
146 PLOGICAL_ADAPTER Adapter
;
147 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
149 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
151 ASSERT(MacBindingHandle
);
152 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
154 ASSERT(AdapterBinding
->Adapter
);
155 Adapter
= AdapterBinding
->Adapter
;
157 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
160 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
161 return NDIS_STATUS_PENDING
;
163 if (MiniIsBusy(Adapter
, NdisWorkItemRequest
)) {
164 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, NdisRequest
, FALSE
);
165 return NDIS_STATUS_PENDING
;
168 return MiniDoRequest(Adapter
, NdisRequest
);
175 IN NDIS_HANDLE MacBindingHandle
)
179 return NDIS_STATUS_FAILURE
;
183 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter
, PNDIS_PACKET Packet
)
186 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
187 return NDIS_STATUS_PENDING
;
190 NDIS_STATUS NdisStatus
;
192 if(MiniIsBusy(Adapter
, NdisWorkItemSend
)) {
193 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, FALSE
);
194 return NDIS_STATUS_PENDING
;
197 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
199 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
201 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
202 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
203 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
204 NdisStatus
= NDIS_STATUS_PENDING
;
206 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
207 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &RaiseOldIrql
);
208 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
209 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
210 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
211 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, RaiseOldIrql
);
213 NdisStatus
= NDIS_GET_PACKET_STATUS(Packet
);
214 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
215 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
216 NdisStatus
= NDIS_STATUS_PENDING
;
222 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
224 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
225 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
226 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
227 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
229 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
230 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &RaiseOldIrql
);
231 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
232 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
233 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, Packet
->Private
.Flags
);
234 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
235 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, RaiseOldIrql
);
237 if (NdisStatus
== NDIS_STATUS_RESOURCES
) {
238 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, Packet
, TRUE
);
239 NdisStatus
= NDIS_STATUS_PENDING
;
251 IN NDIS_HANDLE MacBindingHandle
,
252 IN PNDIS_PACKET Packet
)
254 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
256 * MacBindingHandle = Adapter binding handle
257 * Packet = Pointer to NDIS packet descriptor
259 * NDIS_STATUS_SUCCESS if the packet was successfully sent
260 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
263 PADAPTER_BINDING AdapterBinding
;
264 PLOGICAL_ADAPTER Adapter
;
266 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
268 ASSERT(MacBindingHandle
);
269 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
271 ASSERT(AdapterBinding
);
272 Adapter
= AdapterBinding
->Adapter
;
275 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
277 /* XXX what is this crazy black magic? */
278 Packet
->Reserved
[0] = (ULONG_PTR
)MacBindingHandle
;
281 * Test the packet to see if it is a MAC loopback.
283 * We may have to loop this packet if miniport cannot.
284 * If dest MAC address of packet == MAC address of adapter,
285 * this is a loopback frame.
288 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
289 MiniAdapterHasAddress(Adapter
, Packet
))
292 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, Packet
, FALSE
);
293 return NDIS_STATUS_PENDING
;
295 return ProIndicatePacket(Adapter
, Packet
);
298 return proSendPacketToMiniport(Adapter
, Packet
);
305 IN NDIS_HANDLE NdisBindingHandle
,
306 IN PPNDIS_PACKET PacketArray
,
307 IN UINT NumberOfPackets
)
309 PADAPTER_BINDING AdapterBinding
= NdisBindingHandle
;
310 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
312 NDIS_STATUS NdisStatus
;
315 if(Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)
317 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
319 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
320 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
324 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
325 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &RaiseOldIrql
);
326 (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendPacketsHandler
)(
327 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
, NumberOfPackets
);
328 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, RaiseOldIrql
);
329 for (i
= 0; i
< NumberOfPackets
; i
++)
331 NdisStatus
= NDIS_GET_PACKET_STATUS(PacketArray
[i
]);
332 if (NdisStatus
!= NDIS_STATUS_PENDING
)
333 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
339 if(Adapter
->NdisMiniportBlock
.Flags
& NDIS_ATTRIBUTE_DESERIALIZE
)
341 for (i
= 0; i
< NumberOfPackets
; i
++)
343 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
344 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
345 if (NdisStatus
!= NDIS_STATUS_PENDING
)
346 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
351 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
352 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &RaiseOldIrql
);
353 for (i
= 0; i
< NumberOfPackets
; i
++)
355 NdisStatus
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.SendHandler
)(
356 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, PacketArray
[i
], PacketArray
[i
]->Private
.Flags
);
357 if (NdisStatus
!= NDIS_STATUS_PENDING
)
358 MiniSendComplete(Adapter
, PacketArray
[i
], NdisStatus
);
360 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, RaiseOldIrql
);
368 IN NDIS_HANDLE MacBindingHandle
,
369 IN NDIS_HANDLE MacReceiveContext
,
371 IN UINT BytesToTransfer
,
372 IN OUT PNDIS_PACKET Packet
,
373 OUT PUINT BytesTransferred
)
375 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
377 * MacBindingHandle = Adapter binding handle
378 * MacReceiveContext = MAC receive context
379 * ByteOffset = Offset in packet to place data
380 * BytesToTransfer = Number of bytes to copy into packet
381 * Packet = Pointer to NDIS packet descriptor
382 * BytesTransferred = Address of buffer to place number of bytes copied
385 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
386 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
390 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
392 /* FIXME: Interrupts must be disabled for adapter */
393 /* XXX sd - why is that true? */
395 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
396 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
397 /* NDIS is responsible for looping this packet */
398 NdisCopyFromPacketToPacket(Packet
,
401 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
404 return NDIS_STATUS_SUCCESS
;
407 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
409 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
412 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
417 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
430 OUT PNDIS_STATUS Status
,
431 IN NDIS_HANDLE NdisBindingHandle
)
433 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
435 * Status = Address of buffer for status information
436 * NdisBindingHandle = Handle returned by NdisOpenAdapter
439 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
441 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
443 /* Remove from protocol's bound adapters list */
444 ExInterlockedRemoveEntryList(&AdapterBinding
->ProtocolListEntry
, &AdapterBinding
->ProtocolBinding
->Lock
);
446 /* Remove protocol from adapter's bound protocols list */
447 ExInterlockedRemoveEntryList(&AdapterBinding
->AdapterListEntry
, &AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
);
449 ExFreePool(AdapterBinding
);
451 *Status
= NDIS_STATUS_SUCCESS
;
460 NdisDeregisterProtocol(
461 OUT PNDIS_STATUS Status
,
462 IN NDIS_HANDLE NdisProtocolHandle
)
464 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
466 * Status = Address of buffer for status information
467 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
470 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
472 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
474 /* FIXME: Make sure no adapter bindings exist */
476 /* Remove protocol from global list */
477 ExInterlockedRemoveEntryList(&Protocol
->ListEntry
, &ProtocolListLock
);
479 ExFreePool(Protocol
);
481 *Status
= NDIS_STATUS_SUCCESS
;
491 OUT PNDIS_STATUS Status
,
492 OUT PNDIS_STATUS OpenErrorStatus
,
493 OUT PNDIS_HANDLE NdisBindingHandle
,
494 OUT PUINT SelectedMediumIndex
,
495 IN PNDIS_MEDIUM MediumArray
,
496 IN UINT MediumArraySize
,
497 IN NDIS_HANDLE NdisProtocolHandle
,
498 IN NDIS_HANDLE ProtocolBindingContext
,
499 IN PNDIS_STRING AdapterName
,
501 IN PSTRING AddressingInformation OPTIONAL
)
503 * FUNCTION: Opens an adapter for communication
505 * Status = Address of buffer for status information
506 * OpenErrorStatus = Address of buffer for secondary error code
507 * NdisBindingHandle = Address of buffer for adapter binding handle
508 * SelectedMediumIndex = Address of buffer for selected medium
509 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
510 * MediumArraySize = Number of elements in MediumArray
511 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
512 * ProtocolBindingContext = Pointer to caller suplied context area
513 * AdapterName = Pointer to buffer with name of adapter
514 * OpenOptions = Bitmask with flags passed to next-lower driver
515 * AddressingInformation = Optional pointer to buffer with NIC specific information
520 PLOGICAL_ADAPTER Adapter
;
521 PADAPTER_BINDING AdapterBinding
;
522 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
524 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
526 if(!NdisProtocolHandle
)
528 NDIS_DbgPrint(MAX_TRACE
, ("NdisProtocolHandle is NULL\n"));
529 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
533 Adapter
= MiniLocateDevice(AdapterName
);
536 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
537 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
541 /* Find the media type in the list provided by the protocol driver */
543 for (i
= 0; i
< MediumArraySize
; i
++)
545 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
547 *SelectedMediumIndex
= i
;
555 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
556 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
560 /* Now that we have confirmed that the adapter can be opened, create a binding */
562 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
565 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
566 *Status
= NDIS_STATUS_RESOURCES
;
570 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
572 AdapterBinding
->ProtocolBinding
= Protocol
;
573 AdapterBinding
->Adapter
= Adapter
;
574 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
576 /* Set fields required by some NDIS macros */
577 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
579 /* Set handlers (some NDIS macros require these) */
581 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
582 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
583 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
584 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
585 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
587 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
588 Protocol
->Chars
.RequestCompleteHandler
;
590 /* Put on protocol's bound adapters list */
591 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
593 /* Put protocol on adapter's bound protocols list */
594 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
595 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
597 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
599 *Status
= NDIS_STATUS_SUCCESS
;
604 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status
, IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
)
607 * bind the protocol to all of its miniports
610 * get list of devices from Bind key
611 * call BindAdapterHandler for each
613 OBJECT_ATTRIBUTES ObjectAttributes
;
614 UNICODE_STRING RegistryPath
;
615 WCHAR
*RegistryPathStr
;
618 HANDLE DriverKeyHandle
= NULL
;
619 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
621 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
624 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
625 *Status
= NDIS_STATUS_RESOURCES
;
629 wcscpy(RegistryPathStr
, SERVICES_KEY
);
630 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
631 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
632 wcscat(RegistryPathStr
, LINKAGE_KEY
);
634 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
635 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
637 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
638 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
640 ExFreePool(RegistryPathStr
);
642 if(!NT_SUCCESS(NtStatus
))
644 NDIS_DbgPrint(MIN_TRACE
, ("Unable to open protocol configuration\n"));
645 *Status
= NDIS_STATUS_FAILURE
;
649 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
652 UNICODE_STRING ValueName
;
655 RtlInitUnicodeString(&ValueName
, L
"Bind");
657 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
658 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
660 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value for size\n"));
661 ZwClose(DriverKeyHandle
);
662 *Status
= NDIS_STATUS_FAILURE
;
666 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
669 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
670 ZwClose(DriverKeyHandle
);
671 *Status
= NDIS_STATUS_FAILURE
;
675 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
676 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
678 ZwClose(DriverKeyHandle
);
680 if(!NT_SUCCESS(NtStatus
))
682 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
683 ExFreePool(KeyInformation
);
684 *Status
= NDIS_STATUS_FAILURE
;
689 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
691 DataPtr
+= wcslen(DataPtr
) + 1)
693 /* BindContext is for tracking pending binding operations */
694 VOID
*BindContext
= 0;
695 NDIS_STRING DeviceName
;
696 NDIS_STRING RegistryPath
;
697 WCHAR
*RegistryPathStr
= NULL
;
698 ULONG PathLength
= 0;
700 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
703 * RegistryPath should be:
704 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
706 * This is constructed as follows:
707 * SERVICES_KEY + extracted device name + Protocol name from characteristics
710 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
711 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
712 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
713 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
715 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
718 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
719 ExFreePool(KeyInformation
);
720 *Status
= NDIS_STATUS_RESOURCES
;
724 wcscpy(RegistryPathStr
, SERVICES_KEY
);
725 wcscat(RegistryPathStr
, DataPtr
+ 8 );
726 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
727 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
729 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
731 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
733 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
734 &DeviceName
, &RegistryPath
));
737 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
739 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
741 NDIS_DbgPrint(MID_TRACE
, ("No protocol bind handler specified\n"));
745 *Status
= NDIS_STATUS_SUCCESS
;
746 ExFreePool(KeyInformation
);
754 NdisRegisterProtocol(
755 OUT PNDIS_STATUS Status
,
756 OUT PNDIS_HANDLE NdisProtocolHandle
,
757 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
758 IN UINT CharacteristicsLength
)
760 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
762 * Status = Address of buffer for status information
763 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
764 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
765 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
767 * - you *must* set NdisProtocolHandle before doing anything that could wind up
768 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
769 * - the above implies that the initialization of the protocol block must be complete
772 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
773 * - make this thing able to handle >1 protocol
776 PPROTOCOL_BINDING Protocol
;
780 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
782 *NdisProtocolHandle
= NULL
;
784 /* first validate the PROTOCOL_CHARACTERISTICS */
785 switch (ProtocolCharacteristics
->MajorNdisVersion
)
788 /* we don't really want to support ndis3 drivers - so we complain for now */
789 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
790 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
794 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
798 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
802 *Status
= NDIS_STATUS_BAD_VERSION
;
803 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
807 if (CharacteristicsLength
< MinSize
)
809 NDIS_DbgPrint(MIN_TRACE
, ("Bad protocol characteristics.\n"));
810 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
814 /* set up the protocol block */
815 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
818 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
819 *Status
= NDIS_STATUS_RESOURCES
;
823 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
824 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
826 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
827 if (!NT_SUCCESS(NtStatus
))
829 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
830 ExFreePool(Protocol
);
831 *Status
= NDIS_STATUS_RESOURCES
;
835 KeInitializeSpinLock(&Protocol
->Lock
);
837 InitializeListHead(&Protocol
->AdapterListHead
);
839 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's
840 * BindAdapter handler might need it */
842 *NdisProtocolHandle
= Protocol
;
844 ndisBindMiniportsToProtocol(Status
, &Protocol
->Chars
);
846 if (*Status
== NDIS_STATUS_SUCCESS
) {
847 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
849 ExFreePool(Protocol
);
850 *NdisProtocolHandle
= NULL
;
861 OUT PNDIS_STATUS Status
,
862 IN NDIS_HANDLE NdisBindingHandle
,
863 IN PNDIS_REQUEST NdisRequest
)
865 * FUNCTION: Forwards a request to an NDIS driver
867 * Status = Address of buffer for status information
868 * NdisBindingHandle = Adapter binding handle
869 * NdisRequest = Pointer to request to perform
872 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
882 OUT PNDIS_STATUS Status
,
883 IN NDIS_HANDLE NdisBindingHandle
)
885 *Status
= ProReset(NdisBindingHandle
);
896 OUT PNDIS_STATUS Status
,
897 IN NDIS_HANDLE NdisBindingHandle
,
898 IN PNDIS_PACKET Packet
)
900 * FUNCTION: Forwards a request to send a packet
902 * Status = Address of buffer for status information
903 * NdisBindingHandle = Adapter binding handle
904 * Packet = Pointer to NDIS packet descriptor
907 *Status
= ProSend(NdisBindingHandle
, Packet
);
914 #undef NdisSendPackets
918 IN NDIS_HANDLE NdisBindingHandle
,
919 IN PPNDIS_PACKET PacketArray
,
920 IN UINT NumberOfPackets
)
922 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
929 #undef NdisTransferData
933 OUT PNDIS_STATUS Status
,
934 IN NDIS_HANDLE NdisBindingHandle
,
935 IN NDIS_HANDLE MacReceiveContext
,
937 IN UINT BytesToTransfer
,
938 IN OUT PNDIS_PACKET Packet
,
939 OUT PUINT BytesTransferred
)
941 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
943 * Status = Address of buffer for status information
944 * NdisBindingHandle = Adapter binding handle
945 * MacReceiveContext = MAC receive context
946 * ByteOffset = Offset in packet to place data
947 * BytesToTransfer = Number of bytes to copy into packet
948 * Packet = Pointer to NDIS packet descriptor
949 * BytesTransferred = Address of buffer to place number of bytes copied
952 *Status
= ProTransferData(NdisBindingHandle
,
965 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle
)
967 PPROTOCOL_BINDING Protocol
= NdisProtocolHandle
;
968 NDIS_STATUS NdisStatus
;
970 ndisBindMiniportsToProtocol(&NdisStatus
, &Protocol
->Chars
);
980 IN PNDIS_HANDLE NdisBindingHandle
,
981 OUT PNDIS_HANDLE NdisDriverHandle
)
989 PADAPTER_BINDING Binding
= (PADAPTER_BINDING
)NdisBindingHandle
;
993 *NdisDriverHandle
= NULL
;
997 *NdisDriverHandle
= Binding
->Adapter
->NdisMiniportBlock
.DriverHandle
;