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 /* Put protocol binding struct on global list */
47 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
53 PLOGICAL_ADAPTER Adapter
,
56 * FUNCTION: Indicates a packet to bound protocols
58 * Adapter = Pointer to logical adapter
59 * Packet = Pointer to packet to indicate
61 * STATUS_SUCCESS in all cases
63 * - XXX ATM, this only handles loopback packets - is that its designed function?
69 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
72 MiniDisplayPacket(Packet
);
75 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
77 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
78 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
80 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = Packet
;
81 BufferedLength
= CopyPacketToBuffer(Adapter
->LookaheadBuffer
, Packet
, 0, Adapter
->NdisMiniportBlock
.CurrentLookahead
);
83 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
85 if (BufferedLength
> Adapter
->MediumHeaderSize
)
87 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
88 MiniIndicateData(Adapter
, NULL
, Adapter
->LookaheadBuffer
, Adapter
->MediumHeaderSize
,
89 &Adapter
->LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
90 PacketLength
- Adapter
->MediumHeaderSize
);
94 MiniIndicateData(Adapter
, NULL
, Adapter
->LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
97 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
98 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
100 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()] = NULL
;
102 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
104 return STATUS_SUCCESS
;
110 IN NDIS_HANDLE MacBindingHandle
,
111 IN PNDIS_REQUEST NdisRequest
)
113 * FUNCTION: Forwards a request to an NDIS miniport
115 * MacBindingHandle = Adapter binding handle
116 * NdisRequest = Pointer to request to perform
118 * Status of operation
122 BOOLEAN QueueWorkItem
= FALSE
;
123 NDIS_STATUS NdisStatus
;
124 PADAPTER_BINDING AdapterBinding
;
125 PLOGICAL_ADAPTER Adapter
;
126 PNDIS_REQUEST_MAC_BLOCK MacBlock
= (PNDIS_REQUEST_MAC_BLOCK
)NdisRequest
->MacReserved
;
128 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
130 ASSERT(MacBindingHandle
);
131 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
133 ASSERT(AdapterBinding
->Adapter
);
134 Adapter
= AdapterBinding
->Adapter
;
136 MacBlock
->Binding
= &AdapterBinding
->NdisOpenBlock
;
139 * If the miniport is already busy, queue a workitem
141 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
142 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
144 if(Adapter
->MiniportBusy
)
145 QueueWorkItem
= TRUE
;
148 /* MiniQueueWorkItem must be called at IRQL >= DISPATCH_LEVEL */
151 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, (PVOID
)NdisRequest
);
152 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
153 return NDIS_STATUS_PENDING
;
156 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
158 NdisStatus
= MiniDoRequest(&Adapter
->NdisMiniportBlock
, NdisRequest
);
160 if( NdisStatus
== NDIS_STATUS_PENDING
)
161 Adapter
->MiniportBusy
= TRUE
;
169 IN NDIS_HANDLE MacBindingHandle
)
173 return NDIS_STATUS_FAILURE
;
179 IN NDIS_HANDLE MacBindingHandle
,
180 IN PNDIS_PACKET Packet
)
182 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
184 * MacBindingHandle = Adapter binding handle
185 * Packet = Pointer to NDIS packet descriptor
187 * NDIS_STATUS_SUCCESS always
190 * - Fix return values
191 * - Should queue packet if miniport returns NDIS_STATUS_RESOURCES
192 * - Queue packets directly on the adapters when possible (i.e.
193 * when miniports not busy)
198 PADAPTER_BINDING AdapterBinding
;
199 PLOGICAL_ADAPTER Adapter
;
201 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
203 ASSERT(MacBindingHandle
);
204 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
206 ASSERT(AdapterBinding
);
207 Adapter
= AdapterBinding
->Adapter
;
211 /* if the following is not true, KeRaiseIrql() below will break */
212 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
214 /* XXX what is this crazy black magic? */
215 Packet
->Reserved
[0] = (ULONG_PTR
)MacBindingHandle
;
217 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
218 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &SpinOldIrql
);
221 * Test the packet to see if it is a MAC loopback.
223 * We may have to loop this packet if miniport cannot.
224 * If dest MAC address of packet == MAC address of adapter,
225 * this is a loopback frame.
227 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
228 MiniAdapterHasAddress(Adapter
, Packet
))
230 NDIS_DbgPrint(MIN_TRACE
, ("Queuing packet.\n"));
232 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, (PVOID
)Packet
);
233 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
234 return NDIS_STATUS_PENDING
;
237 NDIS_DbgPrint(MID_TRACE
,("Not a loopback packet\n"));
239 /* This is a normal send packet, not a loopback packet. */
240 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, (PVOID
)Packet
);
241 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
242 NDIS_DbgPrint(MAX_TRACE
, ("Queued a work item and returning\n"));
243 return NDIS_STATUS_PENDING
;
249 IN NDIS_HANDLE NdisBindingHandle
,
250 IN PPNDIS_PACKET PacketArray
,
251 IN UINT NumberOfPackets
)
259 IN NDIS_HANDLE MacBindingHandle
,
260 IN NDIS_HANDLE MacReceiveContext
,
262 IN UINT BytesToTransfer
,
263 IN OUT PNDIS_PACKET Packet
,
264 OUT PUINT BytesTransferred
)
266 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
268 * MacBindingHandle = Adapter binding handle
269 * MacReceiveContext = MAC receive context
270 * ByteOffset = Offset in packet to place data
271 * BytesToTransfer = Number of bytes to copy into packet
272 * Packet = Pointer to NDIS packet descriptor
273 * BytesTransferred = Address of buffer to place number of bytes copied
276 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
277 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
281 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
283 /* FIXME: Interrupts must be disabled for adapter */
284 /* XXX sd - why is that true? */
286 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
287 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
288 /* NDIS is responsible for looping this packet */
289 NdisCopyFromPacketToPacket(Packet
,
292 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
295 return NDIS_STATUS_SUCCESS
;
298 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
300 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
303 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
308 KeLowerIrql(OldIrql
);
321 OUT PNDIS_STATUS Status
,
322 IN NDIS_HANDLE NdisBindingHandle
)
324 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
326 * Status = Address of buffer for status information
327 * NdisBindingHandle = Handle returned by NdisOpenAdapter
331 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
333 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
335 /* Remove from protocol's bound adapters list */
336 KeAcquireSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, &OldIrql
);
337 RemoveEntryList(&AdapterBinding
->ProtocolListEntry
);
338 KeReleaseSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, OldIrql
);
340 /* Remove protocol from adapter's bound protocols list */
341 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
342 KeAcquireSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
343 RemoveEntryList(&AdapterBinding
->AdapterListEntry
);
344 KeReleaseSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
346 ExFreePool(AdapterBinding
);
348 *Status
= NDIS_STATUS_SUCCESS
;
357 NdisDeregisterProtocol(
358 OUT PNDIS_STATUS Status
,
359 IN NDIS_HANDLE NdisProtocolHandle
)
361 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
363 * Status = Address of buffer for status information
364 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
368 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
370 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
372 /* FIXME: Make sure no adapter bindings exist */
374 /* Remove protocol from global list */
375 KeAcquireSpinLock(&ProtocolListLock
, &OldIrql
);
376 RemoveEntryList(&Protocol
->ListEntry
);
377 KeReleaseSpinLock(&ProtocolListLock
, OldIrql
);
379 ExFreePool(Protocol
);
381 *Status
= NDIS_STATUS_SUCCESS
;
391 OUT PNDIS_STATUS Status
,
392 OUT PNDIS_STATUS OpenErrorStatus
,
393 OUT PNDIS_HANDLE NdisBindingHandle
,
394 OUT PUINT SelectedMediumIndex
,
395 IN PNDIS_MEDIUM MediumArray
,
396 IN UINT MediumArraySize
,
397 IN NDIS_HANDLE NdisProtocolHandle
,
398 IN NDIS_HANDLE ProtocolBindingContext
,
399 IN PNDIS_STRING AdapterName
,
401 IN PSTRING AddressingInformation OPTIONAL
)
403 * FUNCTION: Opens an adapter for communication
405 * Status = Address of buffer for status information
406 * OpenErrorStatus = Address of buffer for secondary error code
407 * NdisBindingHandle = Address of buffer for adapter binding handle
408 * SelectedMediumIndex = Address of buffer for selected medium
409 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
410 * MediumArraySize = Number of elements in MediumArray
411 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
412 * ProtocolBindingContext = Pointer to caller suplied context area
413 * AdapterName = Pointer to buffer with name of adapter
414 * OpenOptions = Bitmask with flags passed to next-lower driver
415 * AddressingInformation = Optional pointer to buffer with NIC specific information
420 PLOGICAL_ADAPTER Adapter
;
421 PADAPTER_BINDING AdapterBinding
;
422 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
424 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
426 if(!NdisProtocolHandle
)
428 NDIS_DbgPrint(MAX_TRACE
, ("NdisProtocolHandle is NULL\n"));
429 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
433 Adapter
= MiniLocateDevice(AdapterName
);
436 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
437 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
441 /* Find the media type in the list provided by the protocol driver */
443 for (i
= 0; i
< MediumArraySize
; i
++)
445 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
447 *SelectedMediumIndex
= i
;
455 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
456 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
460 /* Now that we have confirmed that the adapter can be opened, create a binding */
462 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
465 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
466 *Status
= NDIS_STATUS_RESOURCES
;
470 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
472 AdapterBinding
->ProtocolBinding
= Protocol
;
473 AdapterBinding
->Adapter
= Adapter
;
474 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
476 /* Set fields required by some NDIS macros */
477 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
479 /* Set handlers (some NDIS macros require these) */
481 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
482 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
483 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
484 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
485 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
487 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
488 Protocol
->Chars
.RequestCompleteHandler
;
491 /* XXX this looks fishy */
492 /* OK, this really *is* fishy - it bugchecks */
493 /* Put on protocol's bound adapters list */
494 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
497 /* XXX so does this */
498 /* Put protocol on adapter's bound protocols list */
499 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
500 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
502 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
504 *Status
= NDIS_STATUS_SUCCESS
;
513 NdisRegisterProtocol(
514 OUT PNDIS_STATUS Status
,
515 OUT PNDIS_HANDLE NdisProtocolHandle
,
516 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
517 IN UINT CharacteristicsLength
)
519 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
521 * Status = Address of buffer for status information
522 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
523 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
524 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
526 * - you *must* set NdisProtocolHandle before doing anything that could wind up
527 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
528 * - the above implies that the initialization of the protocol block must be complete
531 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
532 * - make this thing able to handle >1 protocol
535 PPROTOCOL_BINDING Protocol
;
538 HANDLE DriverKeyHandle
= NULL
;
539 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
542 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
544 *NdisProtocolHandle
= NULL
;
546 /* first validate the PROTOCOL_CHARACTERISTICS */
547 switch (ProtocolCharacteristics
->MajorNdisVersion
)
550 /* we don't really want to support ndis3 drivers - so we complain for now */
551 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
552 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
556 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
560 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
564 *Status
= NDIS_STATUS_BAD_VERSION
;
565 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
569 if (CharacteristicsLength
< MinSize
)
571 NDIS_DbgPrint(DEBUG_PROTOCOL
, ("Bad protocol characteristics.\n"));
572 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
576 /* set up the protocol block */
577 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
580 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
581 *Status
= NDIS_STATUS_RESOURCES
;
585 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
586 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
588 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
589 if (!NT_SUCCESS(NtStatus
))
591 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
592 ExFreePool(Protocol
);
593 *Status
= NDIS_STATUS_RESOURCES
;
597 KeInitializeSpinLock(&Protocol
->Lock
);
599 InitializeListHead(&Protocol
->AdapterListHead
);
602 * bind the protocol to all of its miniports
605 * get list of devices from Bind key
606 * call BindAdapterHandler for each
609 OBJECT_ATTRIBUTES ObjectAttributes
;
610 UNICODE_STRING RegistryPath
;
611 WCHAR
*RegistryPathStr
;
613 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
616 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
617 ExFreePool(Protocol
);
618 *Status
= NDIS_STATUS_RESOURCES
;
622 wcscpy(RegistryPathStr
, SERVICES_KEY
);
623 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
624 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
625 wcscat(RegistryPathStr
, LINKAGE_KEY
);
627 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
628 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
630 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
631 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
633 ExFreePool(RegistryPathStr
);
635 if(!NT_SUCCESS(NtStatus
))
637 NDIS_DbgPrint(MID_TRACE
, ("Unable to open protocol configuration\n"));
638 ExFreePool(Protocol
);
639 *Status
= NDIS_STATUS_FAILURE
;
644 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
647 UNICODE_STRING ValueName
;
650 RtlInitUnicodeString(&ValueName
, L
"Bind");
652 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
653 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
655 NDIS_DbgPrint(MID_TRACE
, ("Unable to query the Bind value for size\n"));
656 ZwClose(DriverKeyHandle
);
657 ExFreePool(Protocol
);
658 *Status
= NDIS_STATUS_FAILURE
;
662 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
665 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
666 ZwClose(DriverKeyHandle
);
667 ExFreePool(Protocol
);
668 *Status
= NDIS_STATUS_FAILURE
;
672 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
673 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
675 ZwClose(DriverKeyHandle
);
677 if(!NT_SUCCESS(NtStatus
))
679 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
680 ExFreePool(KeyInformation
);
681 ExFreePool(Protocol
);
682 *Status
= NDIS_STATUS_FAILURE
;
687 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
689 DataPtr
+= wcslen(DataPtr
) + 1)
691 /* BindContext is for tracking pending binding operations */
692 VOID
*BindContext
= 0;
693 NDIS_STRING DeviceName
;
694 NDIS_STRING RegistryPath
;
695 WCHAR
*RegistryPathStr
= NULL
;
696 ULONG PathLength
= 0;
698 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
701 * RegistryPath should be:
702 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
704 * This is constructed as follows:
705 * SERVICES_KEY + extracted device name + Protocol name from characteristics
708 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
709 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
710 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
711 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
713 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
716 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
717 ExFreePool(KeyInformation
);
718 ExFreePool(Protocol
);
719 *Status
= NDIS_STATUS_RESOURCES
;
723 wcscpy(RegistryPathStr
, SERVICES_KEY
);
724 wcscat(RegistryPathStr
, DataPtr
+ 8 );
725 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
726 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
728 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
730 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
732 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
733 &DeviceName
, &RegistryPath
));
735 /* XXX SD must do something with bind context */
736 *NdisProtocolHandle
= Protocol
;
739 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
741 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
743 NDIS_DbgPrint(MID_TRACE
, ("No protocol bind handler specified\n"));
747 (*(Protocol->Chars.BindAdapterHandler))(Status, BindContext, &DeviceName, &RegistryPath, 0);
750 if(*Status
== NDIS_STATUS_SUCCESS
)
752 /* Put protocol binding struct on global list */
753 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
757 else if(*Status != NDIS_STATUS_PENDING)
764 ExFreePool(KeyInformation
);
765 *Status
= NDIS_STATUS_SUCCESS
;
775 OUT PNDIS_STATUS Status
,
776 IN NDIS_HANDLE NdisBindingHandle
,
777 IN PNDIS_REQUEST NdisRequest
)
779 * FUNCTION: Forwards a request to an NDIS driver
781 * Status = Address of buffer for status information
782 * NdisBindingHandle = Adapter binding handle
783 * NdisRequest = Pointer to request to perform
786 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
796 OUT PNDIS_STATUS Status
,
797 IN NDIS_HANDLE NdisBindingHandle
)
799 *Status
= ProReset(NdisBindingHandle
);
810 OUT PNDIS_STATUS Status
,
811 IN NDIS_HANDLE NdisBindingHandle
,
812 IN PNDIS_PACKET Packet
)
814 * FUNCTION: Forwards a request to send a packet
816 * Status = Address of buffer for status information
817 * NdisBindingHandle = Adapter binding handle
818 * Packet = Pointer to NDIS packet descriptor
821 *Status
= ProSend(NdisBindingHandle
, Packet
);
828 #undef NdisSendPackets
832 IN NDIS_HANDLE NdisBindingHandle
,
833 IN PPNDIS_PACKET PacketArray
,
834 IN UINT NumberOfPackets
)
836 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
843 #undef NdisTransferData
847 OUT PNDIS_STATUS Status
,
848 IN NDIS_HANDLE NdisBindingHandle
,
849 IN NDIS_HANDLE MacReceiveContext
,
851 IN UINT BytesToTransfer
,
852 IN OUT PNDIS_PACKET Packet
,
853 OUT PUINT BytesTransferred
)
855 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
857 * Status = Address of buffer for status information
858 * NdisBindingHandle = Adapter binding handle
859 * MacReceiveContext = MAC receive context
860 * ByteOffset = Offset in packet to place data
861 * BytesToTransfer = Number of bytes to copy into packet
862 * Packet = Pointer to NDIS packet descriptor
863 * BytesTransferred = Address of buffer to place number of bytes copied
866 *Status
= ProTransferData(NdisBindingHandle
,