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 NDIS_DbgPrint(MAX_TRACE
, ("Setting adapter 0x%x to busy\n"));
149 Adapter
->MiniportBusy
= TRUE
;
153 /* MiniQueueWorkItem must be called at IRQL >= DISPATCH_LEVEL */
156 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, (PVOID
)NdisRequest
);
157 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
158 return NDIS_STATUS_PENDING
;
161 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
163 NdisStatus
= MiniDoRequest(&Adapter
->NdisMiniportBlock
, NdisRequest
);
165 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
166 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
168 NDIS_DbgPrint(MAX_TRACE
, ("Setting adapter 0x%x to free\n"));
169 Adapter
->MiniportBusy
= FALSE
;
171 if (Adapter
->WorkQueueHead
)
172 KeInsertQueueDpc(&Adapter
->NdisMiniportBlock
.DeferredDpc
, NULL
, NULL
);
174 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
182 IN NDIS_HANDLE MacBindingHandle
)
186 return NDIS_STATUS_FAILURE
;
192 IN NDIS_HANDLE MacBindingHandle
,
193 IN PNDIS_PACKET Packet
)
195 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
197 * MacBindingHandle = Adapter binding handle
198 * Packet = Pointer to NDIS packet descriptor
200 * NDIS_STATUS_SUCCESS always
203 * - Fix return values
204 * - Should queue packet if miniport returns NDIS_STATUS_RESOURCES
205 * - Queue packets directly on the adapters when possible (i.e.
206 * when miniports not busy)
211 PADAPTER_BINDING AdapterBinding
;
212 PLOGICAL_ADAPTER Adapter
;
214 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
216 ASSERT(MacBindingHandle
);
217 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
219 ASSERT(AdapterBinding
);
220 Adapter
= AdapterBinding
->Adapter
;
224 /* if the following is not true, KeRaiseIrql() below will break */
225 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
227 /* XXX what is this crazy black magic? */
228 Packet
->Reserved
[0] = (ULONG_PTR
)MacBindingHandle
;
230 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
231 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &SpinOldIrql
);
234 * Test the packet to see if it is a MAC loopback.
236 * We may have to loop this packet if miniport cannot.
237 * If dest MAC address of packet == MAC address of adapter,
238 * this is a loopback frame.
240 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
241 MiniAdapterHasAddress(Adapter
, Packet
))
243 NDIS_DbgPrint(MIN_TRACE
, ("Queuing packet.\n"));
245 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, (PVOID
)Packet
);
246 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
247 return NDIS_STATUS_PENDING
;
250 NDIS_DbgPrint(MID_TRACE
,("Not a loopback packet\n"));
252 /* This is a normal send packet, not a loopback packet. */
253 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, (PVOID
)Packet
);
254 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
255 NDIS_DbgPrint(MAX_TRACE
, ("Queued a work item and returning\n"));
256 return NDIS_STATUS_PENDING
;
262 IN NDIS_HANDLE NdisBindingHandle
,
263 IN PPNDIS_PACKET PacketArray
,
264 IN UINT NumberOfPackets
)
272 IN NDIS_HANDLE MacBindingHandle
,
273 IN NDIS_HANDLE MacReceiveContext
,
275 IN UINT BytesToTransfer
,
276 IN OUT PNDIS_PACKET Packet
,
277 OUT PUINT BytesTransferred
)
279 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
281 * MacBindingHandle = Adapter binding handle
282 * MacReceiveContext = MAC receive context
283 * ByteOffset = Offset in packet to place data
284 * BytesToTransfer = Number of bytes to copy into packet
285 * Packet = Pointer to NDIS packet descriptor
286 * BytesTransferred = Address of buffer to place number of bytes copied
289 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
290 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
294 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
296 /* FIXME: Interrupts must be disabled for adapter */
297 /* XXX sd - why is that true? */
299 if (Packet
== Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()]) {
300 NDIS_DbgPrint(MAX_TRACE
, ("LoopPacket\n"));
301 /* NDIS is responsible for looping this packet */
302 NdisCopyFromPacketToPacket(Packet
,
305 Adapter
->NdisMiniportBlock
.IndicatedPacket
[KeGetCurrentProcessorNumber()],
308 return NDIS_STATUS_SUCCESS
;
311 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
313 Status
= (*Adapter
->NdisMiniportBlock
.DriverHandle
->MiniportCharacteristics
.TransferDataHandler
)(
316 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
321 KeLowerIrql(OldIrql
);
334 OUT PNDIS_STATUS Status
,
335 IN NDIS_HANDLE NdisBindingHandle
)
337 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
339 * Status = Address of buffer for status information
340 * NdisBindingHandle = Handle returned by NdisOpenAdapter
344 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
346 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
348 /* Remove from protocol's bound adapters list */
349 KeAcquireSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, &OldIrql
);
350 RemoveEntryList(&AdapterBinding
->ProtocolListEntry
);
351 KeReleaseSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, OldIrql
);
353 /* Remove protocol from adapter's bound protocols list */
354 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
355 KeAcquireSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
356 RemoveEntryList(&AdapterBinding
->AdapterListEntry
);
357 KeReleaseSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
359 ExFreePool(AdapterBinding
);
361 *Status
= NDIS_STATUS_SUCCESS
;
370 NdisDeregisterProtocol(
371 OUT PNDIS_STATUS Status
,
372 IN NDIS_HANDLE NdisProtocolHandle
)
374 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
376 * Status = Address of buffer for status information
377 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
381 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
383 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
385 /* FIXME: Make sure no adapter bindings exist */
387 /* Remove protocol from global list */
388 KeAcquireSpinLock(&ProtocolListLock
, &OldIrql
);
389 RemoveEntryList(&Protocol
->ListEntry
);
390 KeReleaseSpinLock(&ProtocolListLock
, OldIrql
);
392 ExFreePool(Protocol
);
394 *Status
= NDIS_STATUS_SUCCESS
;
404 OUT PNDIS_STATUS Status
,
405 OUT PNDIS_STATUS OpenErrorStatus
,
406 OUT PNDIS_HANDLE NdisBindingHandle
,
407 OUT PUINT SelectedMediumIndex
,
408 IN PNDIS_MEDIUM MediumArray
,
409 IN UINT MediumArraySize
,
410 IN NDIS_HANDLE NdisProtocolHandle
,
411 IN NDIS_HANDLE ProtocolBindingContext
,
412 IN PNDIS_STRING AdapterName
,
414 IN PSTRING AddressingInformation OPTIONAL
)
416 * FUNCTION: Opens an adapter for communication
418 * Status = Address of buffer for status information
419 * OpenErrorStatus = Address of buffer for secondary error code
420 * NdisBindingHandle = Address of buffer for adapter binding handle
421 * SelectedMediumIndex = Address of buffer for selected medium
422 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
423 * MediumArraySize = Number of elements in MediumArray
424 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
425 * ProtocolBindingContext = Pointer to caller suplied context area
426 * AdapterName = Pointer to buffer with name of adapter
427 * OpenOptions = Bitmask with flags passed to next-lower driver
428 * AddressingInformation = Optional pointer to buffer with NIC specific information
433 PLOGICAL_ADAPTER Adapter
;
434 PADAPTER_BINDING AdapterBinding
;
435 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
437 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
439 if(!NdisProtocolHandle
)
441 NDIS_DbgPrint(MAX_TRACE
, ("NdisProtocolHandle is NULL\n"));
442 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
446 Adapter
= MiniLocateDevice(AdapterName
);
449 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
450 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
454 /* Find the media type in the list provided by the protocol driver */
456 for (i
= 0; i
< MediumArraySize
; i
++)
458 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
])
460 *SelectedMediumIndex
= i
;
468 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
469 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
473 /* Now that we have confirmed that the adapter can be opened, create a binding */
475 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
478 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
479 *Status
= NDIS_STATUS_RESOURCES
;
483 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
485 AdapterBinding
->ProtocolBinding
= Protocol
;
486 AdapterBinding
->Adapter
= Adapter
;
487 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
489 /* Set fields required by some NDIS macros */
490 AdapterBinding
->NdisOpenBlock
.BindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
492 /* Set handlers (some NDIS macros require these) */
494 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
495 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
496 AdapterBinding
->NdisOpenBlock
.SendHandler
= ProSend
;
497 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
498 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
500 AdapterBinding
->NdisOpenBlock
.RequestCompleteHandler
=
501 Protocol
->Chars
.RequestCompleteHandler
;
504 /* XXX this looks fishy */
505 /* OK, this really *is* fishy - it bugchecks */
506 /* Put on protocol's bound adapters list */
507 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
, &AdapterBinding
->ProtocolListEntry
, &Protocol
->Lock
);
510 /* XXX so does this */
511 /* Put protocol on adapter's bound protocols list */
512 NDIS_DbgPrint(MAX_TRACE
, ("acquiring miniport block lock\n"));
513 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
, &AdapterBinding
->AdapterListEntry
, &Adapter
->NdisMiniportBlock
.Lock
);
515 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
517 *Status
= NDIS_STATUS_SUCCESS
;
526 NdisRegisterProtocol(
527 OUT PNDIS_STATUS Status
,
528 OUT PNDIS_HANDLE NdisProtocolHandle
,
529 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
530 IN UINT CharacteristicsLength
)
532 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
534 * Status = Address of buffer for status information
535 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
536 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
537 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
539 * - you *must* set NdisProtocolHandle before doing anything that could wind up
540 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
541 * - the above implies that the initialization of the protocol block must be complete
544 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
545 * - make this thing able to handle >1 protocol
548 PPROTOCOL_BINDING Protocol
;
551 HANDLE DriverKeyHandle
= NULL
;
552 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
555 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
557 *NdisProtocolHandle
= NULL
;
559 /* first validate the PROTOCOL_CHARACTERISTICS */
560 switch (ProtocolCharacteristics
->MajorNdisVersion
)
563 /* we don't really want to support ndis3 drivers - so we complain for now */
564 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
565 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS
);
569 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS
);
573 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS
);
577 *Status
= NDIS_STATUS_BAD_VERSION
;
578 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
582 if (CharacteristicsLength
< MinSize
)
584 NDIS_DbgPrint(DEBUG_PROTOCOL
, ("Bad protocol characteristics.\n"));
585 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
589 /* set up the protocol block */
590 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
593 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
594 *Status
= NDIS_STATUS_RESOURCES
;
598 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
599 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
601 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
602 if (!NT_SUCCESS(NtStatus
))
604 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
605 ExFreePool(Protocol
);
606 *Status
= NDIS_STATUS_RESOURCES
;
610 KeInitializeSpinLock(&Protocol
->Lock
);
612 InitializeListHead(&Protocol
->AdapterListHead
);
615 * bind the protocol to all of its miniports
618 * get list of devices from Bind key
619 * call BindAdapterHandler for each
622 OBJECT_ATTRIBUTES ObjectAttributes
;
623 UNICODE_STRING RegistryPath
;
624 WCHAR
*RegistryPathStr
;
626 RegistryPathStr
= ExAllocatePoolWithTag(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
), NDIS_TAG
+ __LINE__
);
629 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
630 ExFreePool(Protocol
);
631 *Status
= NDIS_STATUS_RESOURCES
;
635 wcscpy(RegistryPathStr
, SERVICES_KEY
);
636 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
637 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
638 wcscat(RegistryPathStr
, LINKAGE_KEY
);
640 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
641 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
643 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
644 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
646 ExFreePool(RegistryPathStr
);
648 if(!NT_SUCCESS(NtStatus
))
650 NDIS_DbgPrint(MID_TRACE
, ("Unable to open protocol configuration\n"));
651 ExFreePool(Protocol
);
652 *Status
= NDIS_STATUS_FAILURE
;
657 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
660 UNICODE_STRING ValueName
;
663 RtlInitUnicodeString(&ValueName
, L
"Bind");
665 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
666 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
&& NtStatus
!= STATUS_SUCCESS
)
668 NDIS_DbgPrint(MID_TRACE
, ("Unable to query the Bind value for size\n"));
669 ZwClose(DriverKeyHandle
);
670 ExFreePool(Protocol
);
671 *Status
= NDIS_STATUS_FAILURE
;
675 KeyInformation
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, NDIS_TAG
+ __LINE__
);
678 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
679 ZwClose(DriverKeyHandle
);
680 ExFreePool(Protocol
);
681 *Status
= NDIS_STATUS_FAILURE
;
685 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
686 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
688 ZwClose(DriverKeyHandle
);
690 if(!NT_SUCCESS(NtStatus
))
692 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
693 ExFreePool(KeyInformation
);
694 ExFreePool(Protocol
);
695 *Status
= NDIS_STATUS_FAILURE
;
700 for (DataPtr
= (WCHAR
*)KeyInformation
->Data
;
702 DataPtr
+= wcslen(DataPtr
) + 1)
704 /* BindContext is for tracking pending binding operations */
705 VOID
*BindContext
= 0;
706 NDIS_STRING DeviceName
;
707 NDIS_STRING RegistryPath
;
708 WCHAR
*RegistryPathStr
= NULL
;
709 ULONG PathLength
= 0;
711 RtlInitUnicodeString(&DeviceName
, DataPtr
); /* we know this is 0-term */
714 * RegistryPath should be:
715 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
717 * This is constructed as follows:
718 * SERVICES_KEY + extracted device name + Protocol name from characteristics
721 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
722 wcslen( DataPtr
+ 8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
723 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
724 ProtocolCharacteristics
->Name
.Length
+ sizeof(WCHAR
); /* Tcpip */
726 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
729 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
730 ExFreePool(KeyInformation
);
731 ExFreePool(Protocol
);
732 *Status
= NDIS_STATUS_RESOURCES
;
736 wcscpy(RegistryPathStr
, SERVICES_KEY
);
737 wcscat(RegistryPathStr
, DataPtr
+ 8 );
738 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
739 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
741 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
743 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
745 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
746 &DeviceName
, &RegistryPath
));
748 /* XXX SD must do something with bind context */
749 *NdisProtocolHandle
= Protocol
;
752 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
754 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
756 NDIS_DbgPrint(MID_TRACE
, ("No protocol bind handler specified\n"));
760 (*(Protocol->Chars.BindAdapterHandler))(Status, BindContext, &DeviceName, &RegistryPath, 0);
763 if(*Status
== NDIS_STATUS_SUCCESS
)
765 /* Put protocol binding struct on global list */
766 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
770 else if(*Status != NDIS_STATUS_PENDING)
777 ExFreePool(KeyInformation
);
778 *Status
= NDIS_STATUS_SUCCESS
;
788 OUT PNDIS_STATUS Status
,
789 IN NDIS_HANDLE NdisBindingHandle
,
790 IN PNDIS_REQUEST NdisRequest
)
792 * FUNCTION: Forwards a request to an NDIS driver
794 * Status = Address of buffer for status information
795 * NdisBindingHandle = Adapter binding handle
796 * NdisRequest = Pointer to request to perform
799 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
809 OUT PNDIS_STATUS Status
,
810 IN NDIS_HANDLE NdisBindingHandle
)
812 *Status
= ProReset(NdisBindingHandle
);
823 OUT PNDIS_STATUS Status
,
824 IN NDIS_HANDLE NdisBindingHandle
,
825 IN PNDIS_PACKET Packet
)
827 * FUNCTION: Forwards a request to send a packet
829 * Status = Address of buffer for status information
830 * NdisBindingHandle = Adapter binding handle
831 * Packet = Pointer to NDIS packet descriptor
834 *Status
= ProSend(NdisBindingHandle
, Packet
);
841 #undef NdisSendPackets
845 IN NDIS_HANDLE NdisBindingHandle
,
846 IN PPNDIS_PACKET PacketArray
,
847 IN UINT NumberOfPackets
)
849 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
856 #undef NdisTransferData
860 OUT PNDIS_STATUS Status
,
861 IN NDIS_HANDLE NdisBindingHandle
,
862 IN NDIS_HANDLE MacReceiveContext
,
864 IN UINT BytesToTransfer
,
865 IN OUT PNDIS_PACKET Packet
,
866 OUT PUINT BytesTransferred
)
868 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
870 * Status = Address of buffer for status information
871 * NdisBindingHandle = Adapter binding handle
872 * MacReceiveContext = MAC receive context
873 * ByteOffset = Offset in packet to place data
874 * BytesToTransfer = Number of bytes to copy into packet
875 * Packet = Pointer to NDIS packet descriptor
876 * BytesTransferred = Address of buffer to place number of bytes copied
879 *Status
= ProTransferData(NdisBindingHandle
,