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
;
29 NdisCompleteBindAdapter(
30 IN NDIS_HANDLE BindAdapterContext
,
31 IN NDIS_STATUS Status
,
32 IN NDIS_STATUS OpenStatus
)
34 * FUNCTION: Indicates a packet to bound protocols
36 * Adapter = Pointer to logical adapter
37 * Packet = Pointer to packet to indicate
41 * - FIXME: partially-implemented
44 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)BindAdapterContext
;
46 if (!NT_SUCCESS(Status
)) return;
48 /* Put protocol binding struct on global list */
49 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
55 PLOGICAL_ADAPTER Adapter
,
58 * FUNCTION: Indicates a packet to bound protocols
60 * Adapter = Pointer to logical adapter
61 * Packet = Pointer to packet to indicate
63 * STATUS_SUCCESS in all cases
65 * - XXX ATM, this only handles loopback packets - is that its designed function?
72 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
75 MiniDisplayPacket(Packet
);
78 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
80 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
82 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
83 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
85 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = Packet
;
86 BufferedLength
= CopyPacketToBuffer(Adapter
->LookaheadBuffer
, Packet
, 0, Adapter
->NdisMiniportBlock
.CurrentLookahead
);
88 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
90 if (BufferedLength
> Adapter
->MediumHeaderSize
)
92 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
93 MiniIndicateData(Adapter
, NULL
, Adapter
->LookaheadBuffer
, Adapter
->MediumHeaderSize
,
94 &Adapter
->LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
95 PacketLength
- Adapter
->MediumHeaderSize
);
99 MiniIndicateData(Adapter
, NULL
, Adapter
->LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
102 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
103 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
105 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = NULL
;
107 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
109 KeLowerIrql(OldIrql
);
111 return STATUS_SUCCESS
;
117 IN NDIS_HANDLE MacBindingHandle
,
118 IN PNDIS_REQUEST NdisRequest
)
120 * FUNCTION: Forwards a request to an NDIS miniport
122 * MacBindingHandle = Adapter binding handle
123 * NdisRequest = Pointer to request to perform
125 * Status of operation
129 PADAPTER_BINDING AdapterBinding
;
130 PLOGICAL_ADAPTER Adapter
;
131 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
133 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
135 ASSERT(MacBindingHandle
);
136 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
138 ASSERT(AdapterBinding
->Adapter
);
139 Adapter
= AdapterBinding
->Adapter
;
141 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
144 * If the miniport is already busy, queue a workitem
146 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
147 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
149 if (Adapter
->MiniportBusy
) {
150 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, (PVOID
)NdisRequest
);
151 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
152 return NDIS_STATUS_PENDING
;
155 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
157 return MiniDoRequest(Adapter
, NdisRequest
);
163 IN NDIS_HANDLE MacBindingHandle
)
167 return NDIS_STATUS_FAILURE
;
173 IN NDIS_HANDLE MacBindingHandle
,
174 IN PNDIS_PACKET Packet
)
176 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
178 * MacBindingHandle = Adapter binding handle
179 * Packet = Pointer to NDIS packet descriptor
181 * NDIS_STATUS_SUCCESS always
184 * - Fix return values
185 * - Should queue packet if miniport returns NDIS_STATUS_RESOURCES
186 * - Queue packets directly on the adapters when possible (i.e.
187 * when miniports not busy)
192 PADAPTER_BINDING AdapterBinding
;
193 PLOGICAL_ADAPTER Adapter
;
195 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
197 ASSERT(MacBindingHandle
);
198 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
200 ASSERT(AdapterBinding
);
201 Adapter
= AdapterBinding
->Adapter
;
205 /* if the following is not true, KeRaiseIrql() below will break */
206 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
208 /* XXX what is this crazy black magic? */
209 Packet
->Reserved
[0] = (ULONG_PTR
)MacBindingHandle
;
211 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
212 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &SpinOldIrql
);
215 * Test the packet to see if it is a MAC loopback.
217 * We may have to loop this packet if miniport cannot.
218 * If dest MAC address of packet == MAC address of adapter,
219 * this is a loopback frame.
221 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
222 MiniAdapterHasAddress(Adapter
, Packet
))
224 NDIS_DbgPrint(MIN_TRACE
, ("Queuing packet.\n"));
226 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, (PVOID
)Packet
);
227 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
228 return NDIS_STATUS_PENDING
;
231 NDIS_DbgPrint(MID_TRACE
,("Not a loopback packet\n"));
233 /* This is a normal send packet, not a loopback packet. */
234 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, (PVOID
)Packet
);
235 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
236 NDIS_DbgPrint(MAX_TRACE
, ("Queued a work item and returning\n"));
237 return NDIS_STATUS_PENDING
;
243 IN NDIS_HANDLE NdisBindingHandle
,
244 IN PPNDIS_PACKET PacketArray
,
245 IN UINT NumberOfPackets
)
253 IN NDIS_HANDLE MacBindingHandle
,
254 IN NDIS_HANDLE MacReceiveContext
,
256 IN UINT BytesToTransfer
,
257 IN OUT PNDIS_PACKET Packet
,
258 OUT PUINT BytesTransferred
)
260 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
262 * MacBindingHandle = Adapter binding handle
263 * MacReceiveContext = MAC receive context
264 * ByteOffset = Offset in packet to place data
265 * BytesToTransfer = Number of bytes to copy into packet
266 * Packet = Pointer to NDIS packet descriptor
267 * BytesTransferred = Address of buffer to place number of bytes copied
270 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
271 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
275 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
277 /* FIXME: Interrupts must be disabled for adapter */
278 /* XXX sd - why is that true? */
280 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
281 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
282 /* NDIS is responsible for looping this packet */
283 NdisCopyFromPacketToPacket(Packet
,
286 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
289 return NDIS_STATUS_SUCCESS
;
292 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
294 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
297 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
302 KeLowerIrql(OldIrql
);
315 OUT PNDIS_STATUS Status
,
316 IN NDIS_HANDLE NdisBindingHandle
)
318 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
320 * Status = Address of buffer for status information
321 * NdisBindingHandle = Handle returned by NdisOpenAdapter
325 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
327 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
329 /* Remove from protocol's bound adapters list */
330 KeAcquireSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, &OldIrql
);
331 RemoveEntryList(&AdapterBinding
->ProtocolListEntry
);
332 KeReleaseSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, OldIrql
);
334 /* Remove protocol from adapter's bound protocols list */
335 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
336 KeAcquireSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
337 RemoveEntryList(&AdapterBinding
->AdapterListEntry
);
338 KeReleaseSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
340 ExFreePool(AdapterBinding
);
342 *Status
= NDIS_STATUS_SUCCESS
;
351 NdisDeregisterProtocol(
352 OUT PNDIS_STATUS Status
,
353 IN NDIS_HANDLE NdisProtocolHandle
)
355 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
357 * Status = Address of buffer for status information
358 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
362 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
364 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
366 /* FIXME: Make sure no adapter bindings exist */
368 /* Remove protocol from global list */
369 KeAcquireSpinLock(&ProtocolListLock
, &OldIrql
);
370 RemoveEntryList(&Protocol
->ListEntry
);
371 KeReleaseSpinLock(&ProtocolListLock
, OldIrql
);
373 ExFreePool(Protocol
);
375 *Status
= NDIS_STATUS_SUCCESS
;
385 OUT PNDIS_STATUS Status
,
386 OUT PNDIS_STATUS OpenErrorStatus
,
387 OUT PNDIS_HANDLE NdisBindingHandle
,
388 OUT PUINT SelectedMediumIndex
,
389 IN PNDIS_MEDIUM MediumArray
,
390 IN UINT MediumArraySize
,
391 IN NDIS_HANDLE NdisProtocolHandle
,
392 IN NDIS_HANDLE ProtocolBindingContext
,
393 IN PNDIS_STRING AdapterName
,
395 IN PSTRING AddressingInformation OPTIONAL
)
397 * FUNCTION: Opens an adapter for communication
399 * Status = Address of buffer for status information
400 * OpenErrorStatus = Address of buffer for secondary error code
401 * NdisBindingHandle = Address of buffer for adapter binding handle
402 * SelectedMediumIndex = Address of buffer for selected medium
403 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
404 * MediumArraySize = Number of elements in MediumArray
405 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
406 * ProtocolBindingContext = Pointer to caller suplied context area
407 * AdapterName = Pointer to buffer with name of adapter
408 * OpenOptions = Bitmask with flags passed to next-lower driver
409 * AddressingInformation = Optional pointer to buffer with NIC specific information
414 PLOGICAL_ADAPTER Adapter
;
415 PADAPTER_BINDING AdapterBinding
;
416 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
418 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
420 if(!NdisProtocolHandle
)
422 NDIS_DbgPrint(MAX_TRACE
, ("NdisProtocolHandle is NULL\n"));
423 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
427 Adapter
= MiniLocateDevice(AdapterName
);
430 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
431 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
435 /* Find the media type in the list provided by the protocol driver */
437 for (i
= 0; i
< MediumArraySize
; i
++)
439 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
441 *SelectedMediumIndex
= i
;
449 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
450 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
454 /* Now that we have confirmed that the adapter can be opened, create a binding */
456 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
459 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
460 *Status
= NDIS_STATUS_RESOURCES
;
464 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
466 AdapterBinding
->ProtocolBinding
= Protocol
;
467 AdapterBinding
->Adapter
= Adapter
;
468 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
470 /* Set fields required by some NDIS macros */
471 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
473 /* Set handlers (some NDIS macros require these) */
475 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
476 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
477 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
478 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
479 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
481 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
482 Protocol
->Chars
.RequestCompleteHandler
;
485 /* XXX this looks fishy */
486 /* OK, this really *is* fishy - it bugchecks */
487 /* Put on protocol's bound adapters list */
488 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
491 /* XXX so does this */
492 /* Put protocol on adapter's bound protocols list */
493 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
494 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
496 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
498 *Status
= NDIS_STATUS_SUCCESS
;
507 NdisRegisterProtocol(
508 OUT PNDIS_STATUS Status
,
509 OUT PNDIS_HANDLE NdisProtocolHandle
,
510 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
511 IN UINT CharacteristicsLength
)
513 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
515 * Status = Address of buffer for status information
516 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
517 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
518 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
520 * - you *must* set NdisProtocolHandle before doing anything that could wind up
521 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
522 * - the above implies that the initialization of the protocol block must be complete
525 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
526 * - make this thing able to handle >1 protocol
529 PPROTOCOL_BINDING Protocol
;
532 HANDLE DriverKeyHandle
= NULL
;
533 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
536 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
538 *NdisProtocolHandle
= NULL
;
540 /* first validate the PROTOCOL_CHARACTERISTICS */
541 switch (ProtocolCharacteristics
->MajorNdisVersion
)
544 /* we don't really want to support ndis3 drivers - so we complain for now */
545 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
546 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
550 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
554 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
558 *Status
= NDIS_STATUS_BAD_VERSION
;
559 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
563 if (CharacteristicsLength
< MinSize
)
565 NDIS_DbgPrint(DEBUG_PROTOCOL
, ("Bad protocol characteristics.\n"));
566 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
570 /* set up the protocol block */
571 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
574 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
575 *Status
= NDIS_STATUS_RESOURCES
;
579 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
580 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
582 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
583 if (!NT_SUCCESS(NtStatus
))
585 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
586 ExFreePool(Protocol
);
587 *Status
= NDIS_STATUS_RESOURCES
;
591 KeInitializeSpinLock(&Protocol
->Lock
);
593 InitializeListHead(&Protocol
->AdapterListHead
);
596 * bind the protocol to all of its miniports
599 * get list of devices from Bind key
600 * call BindAdapterHandler for each
603 OBJECT_ATTRIBUTES ObjectAttributes
;
604 UNICODE_STRING RegistryPath
;
605 WCHAR
*RegistryPathStr
;
607 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
610 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
611 ExFreePool(Protocol
);
612 *Status
= NDIS_STATUS_RESOURCES
;
616 wcscpy(RegistryPathStr
, SERVICES_KEY
);
617 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
618 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
619 wcscat(RegistryPathStr
, LINKAGE_KEY
);
621 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
622 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
624 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
625 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
627 ExFreePool(RegistryPathStr
);
629 if(!NT_SUCCESS(NtStatus
))
631 NDIS_DbgPrint(MID_TRACE
, ("Unable to open protocol configuration\n"));
632 ExFreePool(Protocol
);
633 *Status
= NDIS_STATUS_FAILURE
;
638 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
641 UNICODE_STRING ValueName
;
644 RtlInitUnicodeString(&ValueName
, L
"Bind");
646 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
647 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
649 NDIS_DbgPrint(MID_TRACE
, ("Unable to query the Bind value for size\n"));
650 ZwClose(DriverKeyHandle
);
651 ExFreePool(Protocol
);
652 *Status
= NDIS_STATUS_FAILURE
;
656 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
659 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
660 ZwClose(DriverKeyHandle
);
661 ExFreePool(Protocol
);
662 *Status
= NDIS_STATUS_FAILURE
;
666 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
667 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
669 ZwClose(DriverKeyHandle
);
671 if(!NT_SUCCESS(NtStatus
))
673 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
674 ExFreePool(KeyInformation
);
675 ExFreePool(Protocol
);
676 *Status
= NDIS_STATUS_FAILURE
;
681 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
683 DataPtr
+= wcslen(DataPtr
) + 1)
685 /* BindContext is for tracking pending binding operations */
686 VOID
*BindContext
= 0;
687 NDIS_STRING DeviceName
;
688 NDIS_STRING RegistryPath
;
689 WCHAR
*RegistryPathStr
= NULL
;
690 ULONG PathLength
= 0;
692 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
695 * RegistryPath should be:
696 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
698 * This is constructed as follows:
699 * SERVICES_KEY + extracted device name + Protocol name from characteristics
702 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
703 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
704 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
705 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
707 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
710 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
711 ExFreePool(KeyInformation
);
712 ExFreePool(Protocol
);
713 *Status
= NDIS_STATUS_RESOURCES
;
717 wcscpy(RegistryPathStr
, SERVICES_KEY
);
718 wcscat(RegistryPathStr
, DataPtr
+ 8 );
719 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
720 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
722 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
724 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
726 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
727 &DeviceName
, &RegistryPath
));
729 /* XXX SD must do something with bind context */
730 *NdisProtocolHandle
= Protocol
;
733 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
735 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
737 NDIS_DbgPrint(MID_TRACE
, ("No protocol bind handler specified\n"));
741 (*(Protocol->Chars.BindAdapterHandler))(Status, BindContext, &DeviceName, &RegistryPath, 0);
744 if(*Status
== NDIS_STATUS_SUCCESS
)
746 /* Put protocol binding struct on global list */
747 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
751 else if(*Status != NDIS_STATUS_PENDING)
758 ExFreePool(KeyInformation
);
759 *Status
= NDIS_STATUS_SUCCESS
;
769 OUT PNDIS_STATUS Status
,
770 IN NDIS_HANDLE NdisBindingHandle
,
771 IN PNDIS_REQUEST NdisRequest
)
773 * FUNCTION: Forwards a request to an NDIS driver
775 * Status = Address of buffer for status information
776 * NdisBindingHandle = Adapter binding handle
777 * NdisRequest = Pointer to request to perform
780 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
790 OUT PNDIS_STATUS Status
,
791 IN NDIS_HANDLE NdisBindingHandle
)
793 *Status
= ProReset(NdisBindingHandle
);
804 OUT PNDIS_STATUS Status
,
805 IN NDIS_HANDLE NdisBindingHandle
,
806 IN PNDIS_PACKET Packet
)
808 * FUNCTION: Forwards a request to send a packet
810 * Status = Address of buffer for status information
811 * NdisBindingHandle = Adapter binding handle
812 * Packet = Pointer to NDIS packet descriptor
815 *Status
= ProSend(NdisBindingHandle
, Packet
);
822 #undef NdisSendPackets
826 IN NDIS_HANDLE NdisBindingHandle
,
827 IN PPNDIS_PACKET PacketArray
,
828 IN UINT NumberOfPackets
)
830 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
837 #undef NdisTransferData
841 OUT PNDIS_STATUS Status
,
842 IN NDIS_HANDLE NdisBindingHandle
,
843 IN NDIS_HANDLE MacReceiveContext
,
845 IN UINT BytesToTransfer
,
846 IN OUT PNDIS_PACKET Packet
,
847 OUT PUINT BytesTransferred
)
849 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
851 * Status = Address of buffer for status information
852 * NdisBindingHandle = Adapter binding handle
853 * MacReceiveContext = MAC receive context
854 * ByteOffset = Offset in packet to place data
855 * BytesToTransfer = Number of bytes to copy into packet
856 * Packet = Pointer to NDIS packet descriptor
857 * BytesTransferred = Address of buffer to place number of bytes copied
860 *Status
= ProTransferData(NdisBindingHandle
,