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
17 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
18 #define LINKAGE_KEY L"\\Linkage"
19 #define PARAMETERS_KEY L"\\Parameters\\"
21 LIST_ENTRY ProtocolListHead
;
22 KSPIN_LOCK ProtocolListLock
;
30 NdisCompleteBindAdapter(
31 IN NDIS_HANDLE BindAdapterContext
,
32 IN NDIS_STATUS Status
,
33 IN NDIS_STATUS OpenStatus
)
35 * FUNCTION: Indicates a packet to bound protocols
37 * Adapter = Pointer to logical adapter
38 * Packet = Pointer to packet to indicate
42 * - FIXME: partially-implemented
45 PROTOCOL_BINDING
*Protocol
= (PROTOCOL_BINDING
*)BindAdapterContext
;
47 /* Put protocol binding struct on global list */
48 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
54 PLOGICAL_ADAPTER Adapter
,
57 * FUNCTION: Indicates a packet to bound protocols
59 * Adapter = Pointer to logical adapter
60 * Packet = Pointer to packet to indicate
62 * STATUS_SUCCESS in all cases
64 * - XXX ATM, this only handles loopback packets - is that its designed function?
71 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
74 MiniDisplayPacket(Packet
);
77 NdisQueryPacket(Packet
, NULL
, NULL
, NULL
, &PacketLength
);
79 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
81 Adapter
->LoopPacket
= Packet
;
82 BufferedLength
= CopyPacketToBuffer(Adapter
->LookaheadBuffer
, Packet
, 0, Adapter
->CurLookaheadLength
);
84 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
86 if (BufferedLength
> Adapter
->MediumHeaderSize
)
88 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
89 MiniIndicateData(Adapter
, NULL
, Adapter
->LookaheadBuffer
, Adapter
->MediumHeaderSize
,
90 &Adapter
->LookaheadBuffer
[Adapter
->MediumHeaderSize
], BufferedLength
- Adapter
->MediumHeaderSize
,
91 PacketLength
- Adapter
->MediumHeaderSize
);
95 MiniIndicateData(Adapter
, NULL
, Adapter
->LookaheadBuffer
, Adapter
->MediumHeaderSize
, NULL
, 0, 0);
98 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
100 Adapter
->LoopPacket
= NULL
;
102 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
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
;
123 NDIS_STATUS NdisStatus
;
124 PADAPTER_BINDING AdapterBinding
;
125 PLOGICAL_ADAPTER Adapter
;
127 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
129 ASSERT(MacBindingHandle
);
130 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
132 ASSERT(AdapterBinding
->Adapter
);
133 Adapter
= AdapterBinding
->Adapter
;
136 * If the miniport is already busy, queue a workitem
138 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
140 if(Adapter
->MiniportBusy
)
141 QueueWorkItem
= TRUE
;
143 Adapter
->MiniportBusy
= TRUE
;
145 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
149 MiniQueueWorkItem(Adapter
, NdisWorkItemRequest
, (PVOID
)NdisRequest
, (NDIS_HANDLE
)AdapterBinding
);
150 return NDIS_STATUS_PENDING
;
153 /* MiniportQueryInformation (called by MiniDoRequest) runs at DISPATCH_LEVEL */
154 /* TODO (?): move the irql raise into MiniDoRequest */
155 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
157 NdisStatus
= MiniDoRequest(Adapter
, NdisRequest
);
159 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
161 Adapter
->MiniportBusy
= FALSE
;
163 if (Adapter
->WorkQueueHead
)
164 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
166 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
168 KeLowerIrql(OldIrql
);
176 IN NDIS_HANDLE MacBindingHandle
)
180 return NDIS_STATUS_FAILURE
;
186 IN NDIS_HANDLE MacBindingHandle
,
187 IN PNDIS_PACKET Packet
)
189 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
191 * MacBindingHandle = Adapter binding handle
192 * Packet = Pointer to NDIS packet descriptor
194 * NDIS_STATUS_SUCCESS always
197 * - Fix return values
198 * - Should queue packet if miniport returns NDIS_STATUS_RESOURCES
199 * - Queue packets directly on the adapters when possible (i.e.
200 * when miniports not busy)
204 KIRQL RaiseOldIrql
, SpinOldIrql
;
205 BOOLEAN QueueWorkItem
;
206 NDIS_STATUS NdisStatus
;
207 PADAPTER_BINDING AdapterBinding
;
208 PLOGICAL_ADAPTER Adapter
;
210 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
212 ASSERT(MacBindingHandle
);
213 AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
215 ASSERT(AdapterBinding
);
216 Adapter
= AdapterBinding
->Adapter
;
220 /* if the following is not true, KeRaiseIrql() below will break */
221 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
223 /* XXX what is this crazy black magic? */
224 Packet
->Reserved
[0] = (ULONG_PTR
)MacBindingHandle
;
227 * Acquire this lock in order to see if the miniport is busy.
228 * If it is not busy, we mark it as busy and release the lock.
229 * Else we don't do anything because we have to queue a workitem
232 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &SpinOldIrql
);
235 * if the miniport is marked as busy, we queue the packet as a work item,
236 * else we send the packet directly to the miniport. Sending to the miniport
239 if (Adapter
->MiniportBusy
)
240 QueueWorkItem
= TRUE
;
242 Adapter
->MiniportBusy
= TRUE
;
244 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
247 * Test the packet to see if it is a MAC loopback.
249 * We may have to loop this packet if miniport cannot.
250 * If dest MAC address of packet == MAC address of adapter,
251 * this is a loopback frame.
253 if ((Adapter
->NdisMiniportBlock
.MacOptions
& NDIS_MAC_OPTION_NO_LOOPBACK
) &&
254 MiniAdapterHasAddress(Adapter
, Packet
))
256 NDIS_DbgPrint(MIN_TRACE
, ("Looping packet.\n"));
260 MiniQueueWorkItem(Adapter
, NdisWorkItemSendLoopback
, (PVOID
)Packet
, (NDIS_HANDLE
)AdapterBinding
);
261 return NDIS_STATUS_PENDING
;
264 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
267 * atm this *only* handles loopback packets - it calls MiniIndicateData to
268 * send back to the protocol. FIXME: this will need to be adjusted a bit.
269 * Also, I'm not sure you really have to be at dispatch level for this. It
270 * might use a ReceivePackets handler, which can run <= DISPATCH_LEVEL.
272 NdisStatus
= ProIndicatePacket(Adapter
, Packet
);
274 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
276 Adapter
->MiniportBusy
= FALSE
;
278 if (Adapter
->WorkQueueHead
)
279 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
281 NDIS_DbgPrint(MID_TRACE
,("Failed to insert packet into work queue\n"));
283 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
285 KeLowerIrql(RaiseOldIrql
);
290 NDIS_DbgPrint(MID_TRACE
,("Not a loopback packet\n"));
292 /* This is a normal send packet, not a loopback packet. */
295 MiniQueueWorkItem(Adapter
, NdisWorkItemSend
, (PVOID
)Packet
, (NDIS_HANDLE
)AdapterBinding
);
296 NDIS_DbgPrint(MAX_TRACE
, ("Queued a work item and returning\n"));
297 return NDIS_STATUS_PENDING
;
300 ASSERT(Adapter
->Miniport
);
303 * Call the appropriate send handler
305 * If a miniport provides a SendPackets handler, we always call it. If not, we call the
308 if(Adapter
->Miniport
->Chars
.SendPacketsHandler
)
310 /* TODO: support deserialized miniports by checking for attributes */
311 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
312 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
314 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's SendPackets handler\n"));
315 (*Adapter
->Miniport
->Chars
.SendPacketsHandler
)(Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, &Packet
, 1);
317 KeLowerIrql(RaiseOldIrql
);
319 /* XXX why the hell do we do this? */
320 KeAcquireSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, &SpinOldIrql
);
322 if (Adapter
->WorkQueueHead
)
323 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
325 KeReleaseSpinLock(&Adapter
->NdisMiniportBlock
.Lock
, SpinOldIrql
);
327 NDIS_DbgPrint(MAX_TRACE
, ("MiniportDpc queued; returning NDIS_STATUS_SCUCESS\n"));
329 /* SendPackets handlers return void - they always "succeed" */
330 NdisStatus
= NDIS_STATUS_SUCCESS
;
334 /* Send handlers always run at DISPATCH_LEVEL so we raise here */
335 KeRaiseIrql(DISPATCH_LEVEL
, &RaiseOldIrql
);
337 /* XXX FIXME THIS IS WRONG */
338 /* uh oh... forgot why i thought that... */
340 NDIS_DbgPrint(MAX_TRACE
, ("Calling miniport's Send handler\n"));
341 NdisStatus
= (*Adapter
->Miniport
->Chars
.u1
.SendHandler
)(Adapter
->NdisMiniportBlock
.MiniportAdapterContext
, Packet
, 0);
342 NDIS_DbgPrint(MAX_TRACE
, ("back from miniport's send handler\n"));
344 /* XXX why the hell do we do this? */
345 KeAcquireSpinLockAtDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
347 if (Adapter
->WorkQueueHead
)
348 KeInsertQueueDpc(&Adapter
->MiniportDpc
, NULL
, NULL
);
350 KeReleaseSpinLockFromDpcLevel(&Adapter
->NdisMiniportBlock
.Lock
);
352 KeLowerIrql(RaiseOldIrql
);
355 NDIS_DbgPrint(MAX_TRACE
, ("returning 0x%x\n", NdisStatus
));
362 IN NDIS_HANDLE NdisBindingHandle
,
363 IN PPNDIS_PACKET PacketArray
,
364 IN UINT NumberOfPackets
)
372 IN NDIS_HANDLE MacBindingHandle
,
373 IN NDIS_HANDLE MacReceiveContext
,
375 IN UINT BytesToTransfer
,
376 IN OUT PNDIS_PACKET Packet
,
377 OUT PUINT BytesTransferred
)
379 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
381 * MacBindingHandle = Adapter binding handle
382 * MacReceiveContext = MAC receive context
383 * ByteOffset = Offset in packet to place data
384 * BytesToTransfer = Number of bytes to copy into packet
385 * Packet = Pointer to NDIS packet descriptor
386 * BytesTransferred = Address of buffer to place number of bytes copied
389 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(MacBindingHandle
);
390 PLOGICAL_ADAPTER Adapter
= AdapterBinding
->Adapter
;
392 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
394 /* FIXME: Interrupts must be disabled for adapter */
395 /* XXX sd - why is that true? */
397 if (Packet
== Adapter
->LoopPacket
) {
398 /* NDIS is responsible for looping this packet */
399 NdisCopyFromPacketToPacket(Packet
,
405 return NDIS_STATUS_SUCCESS
;
408 return (*Adapter
->Miniport
->Chars
.u2
.TransferDataHandler
)(
411 Adapter
->NdisMiniportBlock
.MiniportAdapterContext
,
425 OUT PNDIS_STATUS Status
,
426 IN NDIS_HANDLE NdisBindingHandle
)
428 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
430 * Status = Address of buffer for status information
431 * NdisBindingHandle = Handle returned by NdisOpenAdapter
435 PADAPTER_BINDING AdapterBinding
= GET_ADAPTER_BINDING(NdisBindingHandle
);
437 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
439 /* Remove from protocol's bound adapters list */
440 KeAcquireSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, &OldIrql
);
441 RemoveEntryList(&AdapterBinding
->ProtocolListEntry
);
442 KeReleaseSpinLock(&AdapterBinding
->ProtocolBinding
->Lock
, OldIrql
);
444 /* Remove protocol from adapter's bound protocols list */
445 KeAcquireSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, &OldIrql
);
446 RemoveEntryList(&AdapterBinding
->AdapterListEntry
);
447 KeReleaseSpinLock(&AdapterBinding
->Adapter
->NdisMiniportBlock
.Lock
, OldIrql
);
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
471 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
473 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
475 /* FIXME: Make sure no adapter bindings exist */
477 /* Remove protocol from global list */
478 KeAcquireSpinLock(&ProtocolListLock
, &OldIrql
);
479 RemoveEntryList(&Protocol
->ListEntry
);
480 KeReleaseSpinLock(&ProtocolListLock
, OldIrql
);
482 ExFreePool(Protocol
);
484 *Status
= NDIS_STATUS_SUCCESS
;
494 OUT PNDIS_STATUS Status
,
495 OUT PNDIS_STATUS OpenErrorStatus
,
496 OUT PNDIS_HANDLE NdisBindingHandle
,
497 OUT PUINT SelectedMediumIndex
,
498 IN PNDIS_MEDIUM MediumArray
,
499 IN UINT MediumArraySize
,
500 IN NDIS_HANDLE NdisProtocolHandle
,
501 IN NDIS_HANDLE ProtocolBindingContext
,
502 IN PNDIS_STRING AdapterName
,
504 IN PSTRING AddressingInformation OPTIONAL
)
506 * FUNCTION: Opens an adapter for communication
508 * Status = Address of buffer for status information
509 * OpenErrorStatus = Address of buffer for secondary error code
510 * NdisBindingHandle = Address of buffer for adapter binding handle
511 * SelectedMediumIndex = Address of buffer for selected medium
512 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
513 * MediumArraySize = Number of elements in MediumArray
514 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
515 * ProtocolBindingContext = Pointer to caller suplied context area
516 * AdapterName = Pointer to buffer with name of adapter
517 * OpenOptions = Bitmask with flags passed to next-lower driver
518 * AddressingInformation = Optional pointer to buffer with NIC specific information
523 PLOGICAL_ADAPTER Adapter
;
524 PADAPTER_BINDING AdapterBinding
;
525 PPROTOCOL_BINDING Protocol
= GET_PROTOCOL_BINDING(NdisProtocolHandle
);
527 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
529 if(!NdisProtocolHandle
)
531 NDIS_DbgPrint(MAX_TRACE
, ("NdisProtocolHandle is NULL\n"));
532 *OpenErrorStatus
= *Status
= NDIS_STATUS_FAILURE
;
536 Adapter
= MiniLocateDevice(AdapterName
);
538 NDIS_DbgPrint(MIN_TRACE
, ("Adapter not found.\n"));
539 *Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
543 /* Find the media type in the list provided by the protocol driver */
545 for (i
= 0; i
< MediumArraySize
; i
++) {
546 if (Adapter
->NdisMiniportBlock
.MediaType
== MediumArray
[i
]) {
547 *SelectedMediumIndex
= i
;
554 NDIS_DbgPrint(MIN_TRACE
, ("Medium is not supported.\n"));
555 *Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
559 AdapterBinding
= ExAllocatePool(NonPagedPool
, sizeof(ADAPTER_BINDING
));
560 if (!AdapterBinding
) {
561 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
562 *Status
= NDIS_STATUS_RESOURCES
;
566 RtlZeroMemory(AdapterBinding
, sizeof(ADAPTER_BINDING
));
568 AdapterBinding
->ProtocolBinding
= Protocol
;
569 AdapterBinding
->Adapter
= Adapter
;
570 AdapterBinding
->NdisOpenBlock
.ProtocolBindingContext
= ProtocolBindingContext
;
572 /* Set fields required by some NDIS macros */
573 AdapterBinding
->NdisOpenBlock
.MacBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
575 /* Set handlers (some NDIS macros require these) */
577 AdapterBinding
->NdisOpenBlock
.RequestHandler
= ProRequest
;
578 AdapterBinding
->NdisOpenBlock
.ResetHandler
= ProReset
;
579 AdapterBinding
->NdisOpenBlock
.u1
.SendHandler
= ProSend
;
580 AdapterBinding
->NdisOpenBlock
.SendPacketsHandler
= ProSendPackets
;
581 AdapterBinding
->NdisOpenBlock
.TransferDataHandler
= ProTransferData
;
584 /* XXX this looks fishy */
585 /* OK, this really *is* fishy - it bugchecks */
586 /* Put on protocol's bound adapters list */
587 ExInterlockedInsertTailList(&Protocol
->AdapterListHead
,
588 &AdapterBinding
->ProtocolListEntry
,
591 /* XXX so does this */
592 /* Put protocol on adapter's bound protocols list */
593 ExInterlockedInsertTailList(&Adapter
->ProtocolListHead
,
594 &AdapterBinding
->AdapterListEntry
,
595 &Adapter
->NdisMiniportBlock
.Lock
);
597 *NdisBindingHandle
= (NDIS_HANDLE
)AdapterBinding
;
599 *Status
= NDIS_STATUS_SUCCESS
;
608 NdisRegisterProtocol(
609 OUT PNDIS_STATUS Status
,
610 OUT PNDIS_HANDLE NdisProtocolHandle
,
611 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics
,
612 IN UINT CharacteristicsLength
)
614 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
616 * Status = Address of buffer for status information
617 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
618 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
619 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
621 * - you *must* set NdisProtocolHandle before doing anything that could wind up
622 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
623 * - the above implies that the initialization of the protocol block must be complete
626 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
627 * - make this thing able to handle >1 protocol
630 PPROTOCOL_BINDING Protocol
;
633 HANDLE DriverKeyHandle
= NULL
;
634 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
= NULL
;
637 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
639 /* first validate the PROTOCOL_CHARACTERISTICS */
640 switch (ProtocolCharacteristics
->MajorNdisVersion
)
643 /* we don't really want to support ndis3 drivers - so we complain for now */
644 NDIS_DbgPrint(MID_TRACE
, ("NDIS 3 protocol attempting to register\n"));
645 MinSize
= sizeof(NDIS30_PROTOCOL_CHARACTERISTICS_S
);
649 MinSize
= sizeof(NDIS40_PROTOCOL_CHARACTERISTICS_S
);
653 MinSize
= sizeof(NDIS50_PROTOCOL_CHARACTERISTICS_S
);
657 *Status
= NDIS_STATUS_BAD_VERSION
;
658 NDIS_DbgPrint(MIN_TRACE
, ("Incorrect characteristics size\n"));
662 if (CharacteristicsLength
< MinSize
)
664 NDIS_DbgPrint(DEBUG_PROTOCOL
, ("Bad protocol characteristics.\n"));
665 *Status
= NDIS_STATUS_BAD_CHARACTERISTICS
;
669 /* set up the protocol block */
670 Protocol
= ExAllocatePool(NonPagedPool
, sizeof(PROTOCOL_BINDING
));
673 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
674 *Status
= NDIS_STATUS_RESOURCES
;
678 RtlZeroMemory(Protocol
, sizeof(PROTOCOL_BINDING
));
679 RtlCopyMemory(&Protocol
->Chars
, ProtocolCharacteristics
, MinSize
);
681 NtStatus
= RtlUpcaseUnicodeString(&Protocol
->Chars
.Name
, &ProtocolCharacteristics
->Name
, TRUE
);
682 if (!NT_SUCCESS(NtStatus
))
684 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
685 ExFreePool(Protocol
);
686 *Status
= NDIS_STATUS_RESOURCES
;
690 KeInitializeSpinLock(&Protocol
->Lock
);
692 Protocol
->RefCount
= 1;
694 InitializeListHead(&Protocol
->AdapterListHead
);
697 * bind the adapter to all of its miniports
700 * get list of devices from Bind key
701 * call BindAdapterHandler for each
704 OBJECT_ATTRIBUTES ObjectAttributes
;
705 UNICODE_STRING RegistryPath
;
706 WCHAR
*RegistryPathStr
;
708 RegistryPathStr
= ExAllocatePool(PagedPool
, sizeof(SERVICES_KEY
) + ProtocolCharacteristics
->Name
.Length
+ sizeof(LINKAGE_KEY
));
711 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
712 ExFreePool(Protocol
);
713 *Status
= NDIS_STATUS_RESOURCES
;
717 wcscpy(RegistryPathStr
, SERVICES_KEY
);
718 wcsncat(RegistryPathStr
, ((WCHAR
*)ProtocolCharacteristics
->Name
.Buffer
), ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
));
719 RegistryPathStr
[wcslen(SERVICES_KEY
)+ProtocolCharacteristics
->Name
.Length
/sizeof(WCHAR
)] = 0;
720 wcscat(RegistryPathStr
, LINKAGE_KEY
);
722 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
723 NDIS_DbgPrint(MAX_TRACE
, ("Opening configuration key: %wZ\n", &RegistryPath
));
725 InitializeObjectAttributes(&ObjectAttributes
, &RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
726 NtStatus
= ZwOpenKey(&DriverKeyHandle
, KEY_READ
, &ObjectAttributes
);
728 ExFreePool(RegistryPathStr
);
730 if(!NT_SUCCESS(NtStatus
))
732 NDIS_DbgPrint(MID_TRACE
, ("Unable to open protocol configuration\n"));
733 ExFreePool(Protocol
);
734 *Status
= NDIS_STATUS_FAILURE
;
739 NDIS_DbgPrint(MAX_TRACE
, ("Successfully opened the registry configuration\n"));
742 UNICODE_STRING ValueName
;
745 RtlInitUnicodeString(&ValueName
, L
"Bind");
747 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, NULL
, 0, &ResultLength
);
748 if(NtStatus
!= STATUS_BUFFER_OVERFLOW
&& NtStatus
!= STATUS_BUFFER_TOO_SMALL
)
750 NDIS_DbgPrint(MID_TRACE
, ("Unable to query the Bind value for size\n"));
751 ZwClose(DriverKeyHandle
);
752 ExFreePool(Protocol
);
753 *Status
= NDIS_STATUS_FAILURE
;
757 KeyInformation
= ExAllocatePool(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
);
760 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
761 ZwClose(DriverKeyHandle
);
762 ExFreePool(Protocol
);
763 *Status
= NDIS_STATUS_FAILURE
;
767 NtStatus
= ZwQueryValueKey(DriverKeyHandle
, &ValueName
, KeyValuePartialInformation
, KeyInformation
,
768 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + ResultLength
, &ResultLength
);
770 if(!NT_SUCCESS(NtStatus
))
772 NDIS_DbgPrint(MIN_TRACE
, ("Unable to query the Bind value\n"));
773 ZwClose(DriverKeyHandle
);
774 ExFreePool(KeyInformation
);
775 ExFreePool(Protocol
);
776 *Status
= NDIS_STATUS_FAILURE
;
782 while((KeyInformation
->Data
)[DataOffset
])
784 /* BindContext is for tracking pending binding operations */
785 VOID
*BindContext
= 0;
786 NDIS_STRING DeviceName
;
787 NDIS_STRING RegistryPath
;
788 WCHAR
*RegistryPathStr
= NULL
;
789 ULONG PathLength
= 0;
791 RtlInitUnicodeString(&DeviceName
, (WCHAR
*)KeyInformation
->Data
); /* we know this is 0-term */
794 * RegistryPath should be:
795 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
797 * This is constructed as follows:
798 * SERVICES_KEY + extracted device name + Protocol name from characteristics
801 PathLength
= sizeof(SERVICES_KEY
) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
802 wcslen( ((WCHAR
*)KeyInformation
->Data
)+8 ) * sizeof(WCHAR
) + /* Adapter1 (extracted from \Device\Adapter1) */
803 sizeof(PARAMETERS_KEY
) + /* \Parameters\ */
804 ProtocolCharacteristics
->Name
.Length
; /* Tcpip */
806 RegistryPathStr
= ExAllocatePool(PagedPool
, PathLength
);
809 NDIS_DbgPrint(MIN_TRACE
, ("insufficient resources.\n"));
810 ExFreePool(KeyInformation
);
811 ExFreePool(Protocol
);
812 *Status
= NDIS_STATUS_RESOURCES
;
816 wcscpy(RegistryPathStr
, SERVICES_KEY
);
817 wcscat(RegistryPathStr
, (((WCHAR
*)(KeyInformation
->Data
)) +8 ));
818 wcscat(RegistryPathStr
, PARAMETERS_KEY
);
819 wcsncat(RegistryPathStr
, ProtocolCharacteristics
->Name
.Buffer
, ProtocolCharacteristics
->Name
.Length
/ sizeof(WCHAR
) );
821 RegistryPathStr
[PathLength
/sizeof(WCHAR
) - 1] = 0;
823 RtlInitUnicodeString(&RegistryPath
, RegistryPathStr
);
825 NDIS_DbgPrint(MAX_TRACE
, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
826 &DeviceName
, &RegistryPath
));
828 /* XXX SD must do something with bind context */
829 *NdisProtocolHandle
= Protocol
;
832 BIND_HANDLER BindHandler
= ProtocolCharacteristics
->BindAdapterHandler
;
834 BindHandler(Status
, BindContext
, &DeviceName
, &RegistryPath
, 0);
836 NDIS_DbgPrint(MID_TRACE
, ("No protocol bind handler specified\n"));
840 (*(Protocol->Chars.BindAdapterHandler))(Status, BindContext, &DeviceName, &RegistryPath, 0);
843 if(*Status
== NDIS_STATUS_SUCCESS
)
845 /* Put protocol binding struct on global list */
846 ExInterlockedInsertTailList(&ProtocolListHead
, &Protocol
->ListEntry
, &ProtocolListLock
);
850 else if(*Status != NDIS_STATUS_PENDING)
856 DataOffset
+= wcslen((WCHAR
*)KeyInformation
->Data
);
859 *Status
= NDIS_STATUS_SUCCESS
;
869 OUT PNDIS_STATUS Status
,
870 IN NDIS_HANDLE NdisBindingHandle
,
871 IN PNDIS_REQUEST NdisRequest
)
873 * FUNCTION: Forwards a request to an NDIS driver
875 * Status = Address of buffer for status information
876 * NdisBindingHandle = Adapter binding handle
877 * NdisRequest = Pointer to request to perform
880 *Status
= ProRequest(NdisBindingHandle
, NdisRequest
);
890 OUT PNDIS_STATUS Status
,
891 IN NDIS_HANDLE NdisBindingHandle
)
893 *Status
= ProReset(NdisBindingHandle
);
903 OUT PNDIS_STATUS Status
,
904 IN NDIS_HANDLE NdisBindingHandle
,
905 IN PNDIS_PACKET Packet
)
907 * FUNCTION: Forwards a request to send a packet
909 * Status = Address of buffer for status information
910 * NdisBindingHandle = Adapter binding handle
911 * Packet = Pointer to NDIS packet descriptor
914 *Status
= ProSend(NdisBindingHandle
, Packet
);
924 IN NDIS_HANDLE NdisBindingHandle
,
925 IN PPNDIS_PACKET PacketArray
,
926 IN UINT NumberOfPackets
)
928 ProSendPackets(NdisBindingHandle
, PacketArray
, NumberOfPackets
);
938 OUT PNDIS_STATUS Status
,
939 IN NDIS_HANDLE NdisBindingHandle
,
940 IN NDIS_HANDLE MacReceiveContext
,
942 IN UINT BytesToTransfer
,
943 IN OUT PNDIS_PACKET Packet
,
944 OUT PUINT BytesTransferred
)
946 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
948 * Status = Address of buffer for status information
949 * NdisBindingHandle = Adapter binding handle
950 * MacReceiveContext = MAC receive context
951 * ByteOffset = Offset in packet to place data
952 * BytesToTransfer = Number of bytes to copy into packet
953 * Packet = Pointer to NDIS packet descriptor
954 * BytesTransferred = Address of buffer to place number of bytes copied
957 *Status
= ProTransferData(NdisBindingHandle
,