implemented NdisMPciAssignResources and fixed several string length bugs
[reactos.git] / reactos / drivers / net / ndis / ndis / protocol.c
1 /*
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 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10 #include <ndissys.h>
11 #include <miniport.h>
12 #include <protocol.h>
13 #include <buffer.h>
14
15
16 LIST_ENTRY ProtocolListHead;
17 KSPIN_LOCK ProtocolListLock;
18
19 /*
20 * @implemented
21 */
22 VOID
23 EXPORT
24 NdisCompleteBindAdapter(
25 IN NDIS_HANDLE BindAdapterContext,
26 IN NDIS_STATUS Status,
27 IN NDIS_STATUS OpenStatus)
28 /*
29 * FUNCTION: Indicates a packet to bound protocols
30 * ARGUMENTS:
31 * Adapter = Pointer to logical adapter
32 * Packet = Pointer to packet to indicate
33 * RETURNS:
34 * Status of operation
35 */
36 {
37 /*
38 * XXX partially-implemented!
39 *
40 * need to handle error conditions, and i'm not sure this is even what this func should do.
41 * be sure to fix NdisRegisterProtocol before fixing this, though.
42 */
43
44 PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;
45
46 /* Put protocol binding struct on global list */
47 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
48 }
49
50
51 NDIS_STATUS
52 ProIndicatePacket(
53 PLOGICAL_ADAPTER Adapter,
54 PNDIS_PACKET Packet)
55 /*
56 * FUNCTION: Indicates a packet to bound protocols
57 * ARGUMENTS:
58 * Adapter = Pointer to logical adapter
59 * Packet = Pointer to packet to indicate
60 * RETURNS:
61 * Status of operation
62 */
63 {
64 KIRQL OldIrql;
65 UINT Length;
66 UINT Total;
67
68 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
69
70 #ifdef DBG
71 MiniDisplayPacket(Packet);
72 #endif
73
74 NdisQueryPacket(Packet, NULL, NULL, NULL, &Total);
75
76 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
77
78 Adapter->LoopPacket = Packet;
79
80 Length = CopyPacketToBuffer(
81 Adapter->LookaheadBuffer,
82 Packet,
83 0,
84 Adapter->CurLookaheadLength);
85
86 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
87
88 if (Length > Adapter->MediumHeaderSize) {
89 MiniIndicateData(Adapter,
90 NULL,
91 Adapter->LookaheadBuffer,
92 Adapter->MediumHeaderSize,
93 &Adapter->LookaheadBuffer[Adapter->MediumHeaderSize],
94 Length - Adapter->MediumHeaderSize,
95 Total - Adapter->MediumHeaderSize);
96 } else {
97 MiniIndicateData(Adapter,
98 NULL,
99 Adapter->LookaheadBuffer,
100 Adapter->MediumHeaderSize,
101 NULL,
102 0,
103 0);
104 }
105
106 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
107
108 Adapter->LoopPacket = NULL;
109
110 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
111
112 return STATUS_SUCCESS;
113 }
114
115
116 NDIS_STATUS
117 ProRequest(
118 IN NDIS_HANDLE MacBindingHandle,
119 IN PNDIS_REQUEST NdisRequest)
120 /*
121 * FUNCTION: Forwards a request to an NDIS miniport
122 * ARGUMENTS:
123 * MacBindingHandle = Adapter binding handle
124 * NdisRequest = Pointer to request to perform
125 * RETURNS:
126 * Status of operation
127 */
128 {
129 KIRQL OldIrql;
130 BOOLEAN Queue;
131 NDIS_STATUS NdisStatus;
132 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
133 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
134
135 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
136
137 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
138 Queue = Adapter->MiniportBusy;
139 if (Queue) {
140 MiniQueueWorkItem(Adapter,
141 NdisWorkItemRequest,
142 (PVOID)NdisRequest,
143 (NDIS_HANDLE)AdapterBinding);
144 } else {
145 Adapter->MiniportBusy = TRUE;
146 }
147 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
148
149 if (!Queue) {
150 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
151 NdisStatus = MiniDoRequest(Adapter, NdisRequest);
152 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
153 Adapter->MiniportBusy = FALSE;
154 if (Adapter->WorkQueueHead)
155 KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
156 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
157 KeLowerIrql(OldIrql);
158 } else {
159 NdisStatus = NDIS_STATUS_PENDING;
160 }
161 return NdisStatus;
162 }
163
164
165 NDIS_STATUS
166 ProReset(
167 IN NDIS_HANDLE MacBindingHandle)
168 {
169 UNIMPLEMENTED
170
171 return NDIS_STATUS_FAILURE;
172 }
173
174
175 NDIS_STATUS
176 ProSend(
177 IN NDIS_HANDLE MacBindingHandle,
178 IN PNDIS_PACKET Packet)
179 /*
180 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
181 * ARGUMENTS:
182 * MacBindingHandle = Adapter binding handle
183 * Packet = Pointer to NDIS packet descriptor
184 */
185 {
186 KIRQL OldIrql;
187 BOOLEAN Queue;
188 NDIS_STATUS NdisStatus;
189 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
190 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
191
192 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
193
194 /* FIXME: Should queue packet if miniport returns NDIS_STATUS_RESOURCES */
195
196 Packet->Reserved[0] = (ULONG_PTR)MacBindingHandle;
197
198 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
199 Queue = Adapter->MiniportBusy;
200
201 /* We may have to loop this packet if miniport cannot */
202 if (Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) {
203 if (MiniAdapterHasAddress(Adapter, Packet)) {
204 /* Do software loopback because miniport does not support it */
205
206 NDIS_DbgPrint(MIN_TRACE, ("Looping packet.\n"));
207
208 if (Queue) {
209
210 /* FIXME: Packets should properbly be queued directly on the adapter instead */
211
212 MiniQueueWorkItem(Adapter,
213 NdisWorkItemSendLoopback,
214 (PVOID)Packet,
215 (NDIS_HANDLE)AdapterBinding);
216 } else {
217 Adapter->MiniportBusy = TRUE;
218 }
219 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
220
221 if (!Queue) {
222 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
223 NdisStatus = ProIndicatePacket(Adapter, Packet);
224 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
225 Adapter->MiniportBusy = FALSE;
226 if (Adapter->WorkQueueHead)
227 KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
228 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
229 KeLowerIrql(OldIrql);
230 return NdisStatus;
231 } else {
232 return NDIS_STATUS_PENDING;
233 }
234 }
235 }
236
237 if (Queue) {
238
239 /* FIXME: Packets should properbly be queued directly on the adapter instead */
240
241 MiniQueueWorkItem(Adapter,
242 NdisWorkItemSend,
243 (PVOID)Packet,
244 (NDIS_HANDLE)AdapterBinding);
245 } else {
246 Adapter->MiniportBusy = TRUE;
247 }
248 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
249
250 if (!Queue) {
251 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
252 NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
253 Adapter->NdisMiniportBlock.MiniportAdapterContext,
254 Packet,
255 0);
256 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
257 Adapter->MiniportBusy = FALSE;
258 if (Adapter->WorkQueueHead)
259 KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
260 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
261 KeLowerIrql(OldIrql);
262 } else {
263 NdisStatus = NDIS_STATUS_PENDING;
264 }
265 return NdisStatus;
266 }
267
268
269 VOID
270 ProSendPackets(
271 IN NDIS_HANDLE NdisBindingHandle,
272 IN PPNDIS_PACKET PacketArray,
273 IN UINT NumberOfPackets)
274 {
275 UNIMPLEMENTED
276 }
277
278
279 NDIS_STATUS
280 ProTransferData(
281 IN NDIS_HANDLE MacBindingHandle,
282 IN NDIS_HANDLE MacReceiveContext,
283 IN UINT ByteOffset,
284 IN UINT BytesToTransfer,
285 IN OUT PNDIS_PACKET Packet,
286 OUT PUINT BytesTransferred)
287 /*
288 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
289 * ARGUMENTS:
290 * MacBindingHandle = Adapter binding handle
291 * MacReceiveContext = MAC receive context
292 * ByteOffset = Offset in packet to place data
293 * BytesToTransfer = Number of bytes to copy into packet
294 * Packet = Pointer to NDIS packet descriptor
295 * BytesTransferred = Address of buffer to place number of bytes copied
296 */
297 {
298 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
299 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
300
301 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
302
303 /* FIXME: Interrupts must be disabled for adapter */
304
305 if (Packet == Adapter->LoopPacket) {
306 /* NDIS is responsible for looping this packet */
307 NdisCopyFromPacketToPacket(Packet,
308 ByteOffset,
309 BytesToTransfer,
310 Adapter->LoopPacket,
311 0,
312 BytesTransferred);
313 return NDIS_STATUS_SUCCESS;
314 }
315
316 return (*Adapter->Miniport->Chars.u2.TransferDataHandler)(
317 Packet,
318 BytesTransferred,
319 Adapter->NdisMiniportBlock.MiniportAdapterContext,
320 MacReceiveContext,
321 ByteOffset,
322 BytesToTransfer);
323 }
324
325
326
327 /*
328 * @implemented
329 */
330 VOID
331 EXPORT
332 NdisCloseAdapter(
333 OUT PNDIS_STATUS Status,
334 IN NDIS_HANDLE NdisBindingHandle)
335 /*
336 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
337 * ARGUMENTS:
338 * Status = Address of buffer for status information
339 * NdisBindingHandle = Handle returned by NdisOpenAdapter
340 */
341 {
342 KIRQL OldIrql;
343 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(NdisBindingHandle);
344
345 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
346
347 /* Remove from protocol's bound adapters list */
348 KeAcquireSpinLock(&AdapterBinding->ProtocolBinding->Lock, &OldIrql);
349 RemoveEntryList(&AdapterBinding->ProtocolListEntry);
350 KeReleaseSpinLock(&AdapterBinding->ProtocolBinding->Lock, OldIrql);
351
352 /* Remove protocol from adapter's bound protocols list */
353 KeAcquireSpinLock(&AdapterBinding->Adapter->NdisMiniportBlock.Lock, &OldIrql);
354 RemoveEntryList(&AdapterBinding->AdapterListEntry);
355 KeReleaseSpinLock(&AdapterBinding->Adapter->NdisMiniportBlock.Lock, OldIrql);
356
357 ExFreePool(AdapterBinding);
358
359 *Status = NDIS_STATUS_SUCCESS;
360 }
361
362
363 /*
364 * @implemented
365 */
366 VOID
367 EXPORT
368 NdisDeregisterProtocol(
369 OUT PNDIS_STATUS Status,
370 IN NDIS_HANDLE NdisProtocolHandle)
371 /*
372 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
373 * ARGUMENTS:
374 * Status = Address of buffer for status information
375 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
376 */
377 {
378 KIRQL OldIrql;
379 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
380
381 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
382
383 /* FIXME: Make sure no adapter bindings exist */
384
385 /* Remove protocol from global list */
386 KeAcquireSpinLock(&ProtocolListLock, &OldIrql);
387 RemoveEntryList(&Protocol->ListEntry);
388 KeReleaseSpinLock(&ProtocolListLock, OldIrql);
389
390 ExFreePool(Protocol);
391
392 *Status = NDIS_STATUS_SUCCESS;
393 }
394
395
396 /*
397 * @implemented
398 */
399 VOID
400 EXPORT
401 NdisOpenAdapter(
402 OUT PNDIS_STATUS Status,
403 OUT PNDIS_STATUS OpenErrorStatus,
404 OUT PNDIS_HANDLE NdisBindingHandle,
405 OUT PUINT SelectedMediumIndex,
406 IN PNDIS_MEDIUM MediumArray,
407 IN UINT MediumArraySize,
408 IN NDIS_HANDLE NdisProtocolHandle,
409 IN NDIS_HANDLE ProtocolBindingContext,
410 IN PNDIS_STRING AdapterName,
411 IN UINT OpenOptions,
412 IN PSTRING AddressingInformation OPTIONAL)
413 /*
414 * FUNCTION: Opens an adapter for communication
415 * ARGUMENTS:
416 * Status = Address of buffer for status information
417 * OpenErrorStatus = Address of buffer for secondary error code
418 * NdisBindingHandle = Address of buffer for adapter binding handle
419 * SelectedMediumIndex = Address of buffer for selected medium
420 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
421 * MediumArraySize = Number of elements in MediumArray
422 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
423 * ProtocolBindingContext = Pointer to caller suplied context area
424 * AdapterName = Pointer to buffer with name of adapter
425 * OpenOptions = Bitmask with flags passed to next-lower driver
426 * AddressingInformation = Optional pointer to buffer with NIC specific information
427 */
428 {
429 UINT i;
430 BOOLEAN Found;
431 PLOGICAL_ADAPTER Adapter;
432 PADAPTER_BINDING AdapterBinding;
433 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
434
435 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
436
437 Adapter = MiniLocateDevice(AdapterName);
438 if (!Adapter) {
439 NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n"));
440 *Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
441 return;
442 }
443
444 /* Find the media type in the list provided by the protocol driver */
445 Found = FALSE;
446 for (i = 0; i < MediumArraySize; i++) {
447 if (Adapter->NdisMiniportBlock.MediaType == MediumArray[i]) {
448 *SelectedMediumIndex = i;
449 Found = TRUE;
450 break;
451 }
452 }
453
454 if (!Found) {
455 NDIS_DbgPrint(MIN_TRACE, ("Medium is not supported.\n"));
456 *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
457 return;
458 }
459
460 AdapterBinding = ExAllocatePool(NonPagedPool, sizeof(ADAPTER_BINDING));
461 if (!AdapterBinding) {
462 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
463 *Status = NDIS_STATUS_RESOURCES;
464 return;
465 }
466
467 RtlZeroMemory(AdapterBinding, sizeof(ADAPTER_BINDING));
468
469 AdapterBinding->ProtocolBinding = Protocol;
470 AdapterBinding->Adapter = Adapter;
471 AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext;
472
473 /* Set fields required by some NDIS macros */
474 AdapterBinding->NdisOpenBlock.MacBindingHandle = (NDIS_HANDLE)AdapterBinding;
475
476 /* Set handlers (some NDIS macros require these) */
477
478 AdapterBinding->NdisOpenBlock.RequestHandler = ProRequest;
479 AdapterBinding->NdisOpenBlock.ResetHandler = ProReset;
480 AdapterBinding->NdisOpenBlock.u1.SendHandler = ProSend;
481 AdapterBinding->NdisOpenBlock.SendPacketsHandler = ProSendPackets;
482 AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData;
483
484 #if 0
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,
489 &AdapterBinding->ProtocolListEntry,
490 &Protocol->Lock);
491 #endif
492 /* XXX so does this */
493 /* Put protocol on adapter's bound protocols list */
494 ExInterlockedInsertTailList(&Adapter->ProtocolListHead,
495 &AdapterBinding->AdapterListEntry,
496 &Adapter->NdisMiniportBlock.Lock);
497
498 *NdisBindingHandle = (NDIS_HANDLE)AdapterBinding;
499
500 *Status = NDIS_STATUS_SUCCESS;
501 }
502
503
504 /*
505 * @implemented
506 */
507 VOID
508 EXPORT
509 NdisRegisterProtocol(
510 OUT PNDIS_STATUS Status,
511 OUT PNDIS_HANDLE NdisProtocolHandle,
512 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
513 IN UINT CharacteristicsLength)
514 /*
515 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
516 * ARGUMENTS:
517 * Status = Address of buffer for status information
518 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
519 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
520 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
521 * TODO:
522 * break this function up
523 * make this thing able to handle >1 protocol
524 */
525 {
526 PPROTOCOL_BINDING Protocol;
527 NTSTATUS NtStatus;
528 UINT MinSize;
529 HANDLE DriverKeyHandle = NULL;
530 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
531 UINT DataOffset = 0;
532
533 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
534
535 switch (ProtocolCharacteristics->MajorNdisVersion) {
536 case 0x03: /* we don't really want to support ndis3 drivers - so we complainf or now */
537 NDIS_DbgPrint(MID_TRACE, ("Ndis 3 protocol attempting to register\n"));
538 MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS_S);
539 break;
540
541 case 0x04:
542 MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS_S);
543 break;
544
545 case 0x05:
546 MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS_S);
547 break;
548
549 default:
550 *Status = NDIS_STATUS_BAD_VERSION;
551 NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n"));
552 return;
553 }
554
555 if (CharacteristicsLength < MinSize) {
556 NDIS_DbgPrint(DEBUG_PROTOCOL, ("Bad protocol characteristics.\n"));
557 *Status = NDIS_STATUS_BAD_CHARACTERISTICS;
558 return;
559 }
560
561 Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING));
562 if (!Protocol) {
563 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
564 *Status = NDIS_STATUS_RESOURCES;
565 return;
566 }
567
568 RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING));
569 RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize);
570
571 NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name,
572 &ProtocolCharacteristics->Name,
573 TRUE);
574 if (!NT_SUCCESS(NtStatus)) {
575 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
576 ExFreePool(Protocol);
577 *Status = NDIS_STATUS_RESOURCES;
578 return;
579 }
580
581 KeInitializeSpinLock(&Protocol->Lock);
582
583 Protocol->RefCount = 1;
584
585 InitializeListHead(&Protocol->AdapterListHead);
586
587 /*
588 * bind the adapter to all of its miniports
589 *
590 * open registry path
591 * get list of devices from Bind key
592 * call BindAdapterHandler for each
593 */
594 {
595 OBJECT_ATTRIBUTES ObjectAttributes;
596 UNICODE_STRING RegistryPath;
597 WCHAR *RegistryPathStr;
598
599 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
600 #define LINKAGE_KEY L"\\Linkage"
601
602 RegistryPathStr = ExAllocatePool(PagedPool,
603 sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY));
604 if(!RegistryPathStr)
605 {
606 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
607 ExFreePool(Protocol);
608 *Status = NDIS_STATUS_RESOURCES;
609 return;
610 }
611
612 wcscpy(RegistryPathStr, SERVICES_KEY);
613 wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer),
614 ProtocolCharacteristics->Name.Length / sizeof(WCHAR));
615 RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0;
616 wcscat(RegistryPathStr, LINKAGE_KEY);
617
618 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
619 NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath));
620
621 InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
622 NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes);
623
624 ExFreePool(RegistryPathStr);
625
626 if(!NT_SUCCESS(NtStatus))
627 {
628 NDIS_DbgPrint(MID_TRACE, ("Unable to open protocol configuration\n"));
629 ExFreePool(Protocol);
630 *Status = NDIS_STATUS_FAILURE;
631 return;
632 }
633 }
634
635 NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n"));
636
637 {
638 UNICODE_STRING ValueName;
639 ULONG Length;
640 ULONG ResultLength;
641
642 RtlInitUnicodeString(&ValueName, L"Bind");
643
644 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength);
645 if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL)
646 {
647 NDIS_DbgPrint(MID_TRACE, ("Unable to query the Bind value for size\n"));
648 ZwClose(DriverKeyHandle);
649 ExFreePool(Protocol);
650 *Status = NDIS_STATUS_FAILURE;
651 return;
652 }
653
654 KeyInformation = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength);
655 if(!KeyInformation)
656 {
657 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
658 ZwClose(DriverKeyHandle);
659 ExFreePool(Protocol);
660 *Status = NDIS_STATUS_FAILURE;
661 return;
662 }
663
664 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation,
665 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength);
666
667 if(!NT_SUCCESS(NtStatus))
668 {
669 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n"));
670 ZwClose(DriverKeyHandle);
671 ExFreePool(KeyInformation);
672 ExFreePool(Protocol);
673 *Status = NDIS_STATUS_FAILURE;
674 return;
675 }
676 }
677
678 DataOffset = 0;
679 while((KeyInformation->Data)[DataOffset])
680 {
681 /* BindContext is for tracking pending binding operations */
682 VOID *BindContext = 0;
683 NDIS_STRING DeviceName;
684 NDIS_STRING RegistryPath;
685 WCHAR *RegistryPathStr = NULL;
686 ULONG PathLength = 0;
687
688 RtlInitUnicodeString(&DeviceName, (WCHAR *)KeyInformation->Data); /* we know this is 0-term */
689
690 /*
691 * RegistryPath should be:
692 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
693 *
694 * This is constructed as follows:
695 * SERVICES_KEY + extracted device name + Protocol name from characteristics
696 */
697 #define PARAMETERS_KEY L"\\Parameters\\"
698
699 PathLength = sizeof(SERVICES_KEY) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
700 wcslen( ((WCHAR *)KeyInformation->Data)+8 ) * sizeof(WCHAR) + /* Adapter1 (extracted from \Device\Adapter1) */
701 sizeof(PARAMETERS_KEY) + /* \Parameters\ */
702 ProtocolCharacteristics->Name.Length; /* Tcpip */
703
704 RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
705 if(!RegistryPathStr)
706 {
707 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
708 ExFreePool(KeyInformation);
709 ExFreePool(Protocol);
710 *Status = NDIS_STATUS_RESOURCES;
711 return;
712 }
713
714 wcscpy(RegistryPathStr, SERVICES_KEY);
715 wcscat(RegistryPathStr, (((WCHAR *)(KeyInformation->Data)) +8 ));
716 wcscat(RegistryPathStr, PARAMETERS_KEY);
717 wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
718
719 RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0;
720
721 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
722
723 NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
724 &DeviceName, &RegistryPath));
725
726 /* XXX SD must do something with bind context */
727 {
728 BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler;
729 if(BindHandler)
730 BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0);
731 else
732 NDIS_DbgPrint(MID_TRACE, ("No protocol bind handler specified\n"));
733 }
734 /*
735 (*(Protocol->Chars.BindAdapterHandler))(Status, BindContext, &DeviceName, &RegistryPath, 0);
736 */
737
738 if(*Status == NDIS_STATUS_SUCCESS)
739 {
740 /* Put protocol binding struct on global list */
741 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
742 }
743 /*
744 else if(*Status != NDIS_STATUS_PENDING)
745 {
746 // what to do here?
747 }
748 */
749
750 DataOffset += wcslen((WCHAR *)KeyInformation->Data);
751 }
752
753 *NdisProtocolHandle = Protocol;
754 *Status = NDIS_STATUS_SUCCESS;
755 }
756
757
758 /*
759 * @implemented
760 */
761 VOID
762 EXPORT
763 NdisRequest(
764 OUT PNDIS_STATUS Status,
765 IN NDIS_HANDLE NdisBindingHandle,
766 IN PNDIS_REQUEST NdisRequest)
767 /*
768 * FUNCTION: Forwards a request to an NDIS driver
769 * ARGUMENTS:
770 * Status = Address of buffer for status information
771 * NdisBindingHandle = Adapter binding handle
772 * NdisRequest = Pointer to request to perform
773 */
774 {
775 *Status = ProRequest(NdisBindingHandle, NdisRequest);
776 }
777
778
779 /*
780 * @implemented
781 */
782 VOID
783 EXPORT
784 NdisReset(
785 OUT PNDIS_STATUS Status,
786 IN NDIS_HANDLE NdisBindingHandle)
787 {
788 *Status = ProReset(NdisBindingHandle);
789 }
790
791
792 /*
793 * @implemented
794 */
795 VOID
796 EXPORT
797 NdisSend(
798 OUT PNDIS_STATUS Status,
799 IN NDIS_HANDLE NdisBindingHandle,
800 IN PNDIS_PACKET Packet)
801 /*
802 * FUNCTION: Forwards a request to send a packet
803 * ARGUMENTS:
804 * Status = Address of buffer for status information
805 * NdisBindingHandle = Adapter binding handle
806 * Packet = Pointer to NDIS packet descriptor
807 */
808 {
809 *Status = ProSend(NdisBindingHandle, Packet);
810 }
811
812
813 /*
814 * @implemented
815 */
816 VOID
817 EXPORT
818 NdisSendPackets(
819 IN NDIS_HANDLE NdisBindingHandle,
820 IN PPNDIS_PACKET PacketArray,
821 IN UINT NumberOfPackets)
822 {
823 ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets);
824 }
825
826
827 /*
828 * @implemented
829 */
830 VOID
831 EXPORT
832 NdisTransferData(
833 OUT PNDIS_STATUS Status,
834 IN NDIS_HANDLE NdisBindingHandle,
835 IN NDIS_HANDLE MacReceiveContext,
836 IN UINT ByteOffset,
837 IN UINT BytesToTransfer,
838 IN OUT PNDIS_PACKET Packet,
839 OUT PUINT BytesTransferred)
840 /*
841 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
842 * ARGUMENTS:
843 * Status = Address of buffer for status information
844 * NdisBindingHandle = Adapter binding handle
845 * MacReceiveContext = MAC receive context
846 * ByteOffset = Offset in packet to place data
847 * BytesToTransfer = Number of bytes to copy into packet
848 * Packet = Pointer to NDIS packet descriptor
849 * BytesTransferred = Address of buffer to place number of bytes copied
850 */
851 {
852 *Status = ProTransferData(NdisBindingHandle,
853 MacReceiveContext,
854 ByteOffset,
855 BytesToTransfer,
856 Packet,
857 BytesTransferred);
858 }
859
860 /* EOF */