[NDIS]
[reactos.git] / reactos / drivers / network / ndis / ndis / config.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/config.c
5 * PURPOSE: NDIS Configuration Services
6 * PROGRAMMERS: Vizzini (vizzini@plasmic.com)
7 * REVISIONS:
8 * Vizzini 07-28-2003 Created
9 * NOTES:
10 * - Resource tracking has to be implemented here because of the design of the NDIS API.
11 * Whenever a read operation is performed, the NDIS library allocates space and returns
12 * it. A linked list is kept associated with every handle of the memory allocated to
13 * it. When the handle is closed, the resources are systematically released.
14 * - The NDIS_HANDLE Configuraiton context is no longer a registry handle. An opaque struct
15 * had to be created to allow for resource tracking. This means that Miniports cannot just
16 * pass this NDIS_HANDLE to things like ZwQueryValueKey(). I don't thknk they do (they
17 * certainly should not), but it should be kept in mind.
18 * UPDATE: I just found this in the NTDDK:
19 * NdisOpenProtocolConfiguration returns a handle for the
20 * HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NICDriverInstance\Parameters\ProtocolName
21 * registry key. XXX This is a problem. Following that, the DDK instructs programmers
22 * to use NdisReadConfiguration and NdisWriteConfiguration. No telling what the world's idiots
23 * have done with this.
24 * - I have tried to stick to the DDK's definition of what return values are possible, which
25 * has resulted in stupid return values in some cases. I do use STATUS_RESOURCES in a few
26 * places that the DDK doesn't explicitly mention it, though.
27 * - There's a general reliance on the fact that UNICODE_STRING.Length doesn't include a trailing
28 * 0, which it shouldn't
29 * - I added support for NdisParameterBinary. It's at the end of the struct. I wonder if
30 * it'll break things.
31 * - All the routines in this file are PASSIVE_LEVEL only, and all memory is PagedPool
32 */
33
34 #include "ndissys.h"
35
36 #define PARAMETERS_KEY L"Parameters" /* The parameters subkey under the device-specific key */
37
38 /*
39 * @implemented
40 */
41 VOID
42 EXPORT
43 NdisWriteConfiguration(
44 OUT PNDIS_STATUS Status,
45 IN NDIS_HANDLE ConfigurationHandle,
46 IN PNDIS_STRING Keyword,
47 IN PNDIS_CONFIGURATION_PARAMETER ParameterValue)
48 /*
49 * FUNCTION: Writes a configuration value to the registry
50 * ARGUMENTS:
51 * Status: Pointer to a caller-supplied NDIS_STATUS where we return status
52 * ConfigurationHandle: The Configuration Handle passed back from the call to one of the Open functions
53 * Keyword: The registry value name to write
54 * ParameterValue: The value data to write
55 * RETURNS:
56 * NDIS_STATUS_SUCCESS - the operation completed successfully
57 * NDIS_STATUS_NOT_SUPPORTED - The parameter type is not supported
58 * NDIS_STATUS_RESOURCES - out of memory, etc.
59 * NDIS_STATUS_FAILURE - any other failure
60 * NOTES:
61 * There's a cryptic comment in the ddk implying that this function allocates and keeps memory.
62 * I don't know why tho so i free everything before return. comments welcome.
63 */
64 {
65 ULONG ParameterType;
66 ULONG DataSize;
67 PVOID Data;
68 WCHAR Buff[11];
69
70 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
71
72 /* reset parameter type to standard reg types */
73 switch(ParameterValue->ParameterType)
74 {
75 case NdisParameterHexInteger:
76 case NdisParameterInteger:
77 {
78 UNICODE_STRING Str;
79
80 Str.Buffer = (PWSTR) &Buff;
81 Str.MaximumLength = (USHORT)sizeof(Buff);
82 Str.Length = 0;
83
84 ParameterType = REG_SZ;
85 if (!NT_SUCCESS(RtlIntegerToUnicodeString(
86 ParameterValue->ParameterData.IntegerData,
87 (ParameterValue->ParameterType == NdisParameterInteger) ? 10 : 16, &Str)))
88 {
89 NDIS_DbgPrint(MIN_TRACE, ("RtlIntegerToUnicodeString failed (%x)\n", *Status));
90 *Status = NDIS_STATUS_FAILURE;
91 return;
92 }
93 Data = Str.Buffer;
94 DataSize = Str.Length;
95 }
96 break;
97 case NdisParameterString:
98 case NdisParameterMultiString:
99 ParameterType = (ParameterValue->ParameterType == NdisParameterString) ? REG_SZ : REG_MULTI_SZ;
100 Data = ParameterValue->ParameterData.StringData.Buffer;
101 DataSize = ParameterValue->ParameterData.StringData.Length;
102 break;
103
104 /* New (undocumented) addition to 2k ddk */
105 case NdisParameterBinary:
106 ParameterType = REG_BINARY;
107 Data = ParameterValue->ParameterData.BinaryData.Buffer;
108 DataSize = ParameterValue->ParameterData.BinaryData.Length;
109 break;
110
111 default:
112 *Status = NDIS_STATUS_NOT_SUPPORTED;
113 return;
114 }
115
116 *Status = ZwSetValueKey(((PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle)->Handle,
117 Keyword, 0, ParameterType, Data, DataSize);
118
119 if(*Status != STATUS_SUCCESS) {
120 NDIS_DbgPrint(MIN_TRACE, ("ZwSetValueKey failed (%x)\n", *Status));
121 *Status = NDIS_STATUS_FAILURE;
122 } else
123 *Status = NDIS_STATUS_SUCCESS;
124 }
125
126
127 /*
128 * @implemented
129 */
130 VOID
131 EXPORT
132 NdisCloseConfiguration(
133 IN NDIS_HANDLE ConfigurationHandle)
134 /*
135 * FUNCTION: Closes handles and releases per-handle resources
136 * ARGUMENTS:
137 * ConfigurationHandle - pointer to the context with the resources to free
138 */
139 {
140 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext = (PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle;
141 PMINIPORT_RESOURCE Resource;
142 PNDIS_CONFIGURATION_PARAMETER ParameterValue;
143 PLIST_ENTRY CurrentEntry;
144
145 while((CurrentEntry = ExInterlockedRemoveHeadList(&ConfigurationContext->ResourceListHead,
146 &ConfigurationContext->ResourceLock)) != NULL)
147 {
148 Resource = CONTAINING_RECORD(CurrentEntry, MINIPORT_RESOURCE, ListEntry);
149 switch(Resource->ResourceType)
150 {
151 case MINIPORT_RESOURCE_TYPE_REGISTRY_DATA:
152 ParameterValue = Resource->Resource;
153
154 switch (ParameterValue->ParameterType)
155 {
156 case NdisParameterBinary:
157 ExFreePool(ParameterValue->ParameterData.BinaryData.Buffer);
158 break;
159
160 case NdisParameterString:
161 case NdisParameterMultiString:
162 ExFreePool(ParameterValue->ParameterData.StringData.Buffer);
163 break;
164
165 default:
166 break;
167 }
168
169 /* Fall through to free NDIS_CONFIGURATION_PARAMETER struct */
170
171 case MINIPORT_RESOURCE_TYPE_MEMORY:
172 NDIS_DbgPrint(MAX_TRACE,("freeing 0x%x\n", Resource->Resource));
173 ExFreePool(Resource->Resource);
174 break;
175
176 default:
177 NDIS_DbgPrint(MIN_TRACE,("Unknown resource type: %d\n", Resource->ResourceType));
178 break;
179 }
180
181 ExFreePool(Resource);
182 }
183
184 ZwClose(ConfigurationContext->Handle);
185 }
186
187
188 /*
189 * @implemented
190 */
191 VOID
192 EXPORT
193 NdisOpenConfiguration(
194 OUT PNDIS_STATUS Status,
195 OUT PNDIS_HANDLE ConfigurationHandle,
196 IN NDIS_HANDLE WrapperConfigurationContext)
197 /*
198 * FUNCTION: Opens the configuration key and sets up resource tracking for the returned handle
199 * ARGUMENTS:
200 * Status: Pointer to a caller-supplied NDIS_STATUS that is filled in with a return value
201 * ConfigurationHandle: Pointer to an opaque configuration handle returned on success
202 * WrapperConfigurationContext: handle originally passed back from NdisInitializeWrapper
203 * RETURNS:
204 * NDIS_STATUS_SUCCESS: the operation completed successfully
205 * NDIS_STATUS_FAILURE: the operation failed
206 * NOTES:
207 * I think this is the parameters key; please verify.
208 */
209 {
210 HANDLE KeyHandle;
211 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
212 PNDIS_WRAPPER_CONTEXT WrapperContext = (PNDIS_WRAPPER_CONTEXT)WrapperConfigurationContext;
213 HANDLE RootKeyHandle = WrapperContext->RegistryHandle;
214
215 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
216
217 *ConfigurationHandle = NULL;
218
219 *Status = ZwDuplicateObject(NtCurrentProcess(), RootKeyHandle,
220 NtCurrentProcess(), &KeyHandle, 0, 0,
221 DUPLICATE_SAME_ACCESS);
222 if(!NT_SUCCESS(*Status))
223 {
224 NDIS_DbgPrint(MIN_TRACE, ("Failed to open registry configuration for this miniport\n"));
225 *Status = NDIS_STATUS_FAILURE;
226 return;
227 }
228
229 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
230 if(!ConfigurationContext)
231 {
232 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
233 ZwClose(KeyHandle);
234 *Status = NDIS_STATUS_RESOURCES;
235 return;
236 }
237
238 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
239 InitializeListHead(&ConfigurationContext->ResourceListHead);
240
241 ConfigurationContext->Handle = KeyHandle;
242
243 *ConfigurationHandle = (NDIS_HANDLE)ConfigurationContext;
244 *Status = NDIS_STATUS_SUCCESS;
245
246 NDIS_DbgPrint(MAX_TRACE,("returning success\n"));
247 }
248
249
250 /*
251 * @implemented
252 */
253 VOID
254 EXPORT
255 NdisOpenProtocolConfiguration(
256 OUT PNDIS_STATUS Status,
257 OUT PNDIS_HANDLE ConfigurationHandle,
258 IN PNDIS_STRING ProtocolSection)
259 /*
260 * FUNCTION: Open the configuration key and set up resource tracking for the protocol
261 * ARGUMENTS:
262 * Status: caller-allocated buffer where status is returned
263 * ConfigurationHandle: spot to return the opaque configuration context
264 * ProtocolSection: configuration string originally passed in to ProtocolBindAdapter
265 * RETURNS:
266 * NDIS_STATUS_SUCCESS: the operation was a success
267 * NDIS_STATUS_FAILURE: the operation was not a success
268 * NOTES:
269 * I think this is the per-device (adapter) parameters\{ProtocolName} key; please verify.
270 */
271 {
272 OBJECT_ATTRIBUTES KeyAttributes;
273 UNICODE_STRING KeyNameU;
274 HANDLE KeyHandle;
275 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
276
277 KeyNameU.Length = 0;
278 KeyNameU.MaximumLength = ProtocolSection->Length + sizeof(PARAMETERS_KEY) + sizeof(UNICODE_NULL);
279 KeyNameU.Buffer = ExAllocatePool(PagedPool, KeyNameU.MaximumLength);
280 if(!KeyNameU.Buffer)
281 {
282 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
283 *ConfigurationHandle = NULL;
284 *Status = NDIS_STATUS_FAILURE;
285 return;
286 }
287
288 RtlCopyUnicodeString(&KeyNameU, ProtocolSection);
289 RtlAppendUnicodeToString(&KeyNameU, PARAMETERS_KEY);
290 InitializeObjectAttributes(&KeyAttributes, &KeyNameU, OBJ_CASE_INSENSITIVE, NULL, NULL);
291
292 *Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
293
294 ExFreePool(KeyNameU.Buffer);
295
296 if(*Status != NDIS_STATUS_SUCCESS)
297 {
298 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
299 *ConfigurationHandle = NULL;
300 *Status = NDIS_STATUS_FAILURE;
301 return;
302 }
303
304 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
305 if(!ConfigurationContext)
306 {
307 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
308 ZwClose(KeyHandle);
309 *ConfigurationHandle = NULL;
310 *Status = NDIS_STATUS_FAILURE;
311 return;
312 }
313
314 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
315 InitializeListHead(&ConfigurationContext->ResourceListHead);
316
317 ConfigurationContext->Handle = KeyHandle;
318
319 *ConfigurationHandle = (NDIS_HANDLE)ConfigurationContext;
320 *Status = NDIS_STATUS_SUCCESS;
321 }
322
323
324 /*
325 * @implemented
326 */
327 VOID
328 EXPORT
329 NdisReadConfiguration(
330 OUT PNDIS_STATUS Status,
331 OUT PNDIS_CONFIGURATION_PARAMETER * ParameterValue,
332 IN NDIS_HANDLE ConfigurationHandle,
333 IN PNDIS_STRING Keyword,
334 IN NDIS_PARAMETER_TYPE ParameterType)
335 /*
336 * FUNCTION: Read a configuration value from the registry, tracking its resources
337 * ARGUMENTS:
338 * Status: points to a place to write status into
339 * ParameterValue: Pointer to receive a newly-allocated parameter structure
340 * ConfigurationHandle: handle originally returned by an open function
341 * Keyword: Value name to read, or one of the following constants:
342 * Environment - returns NdisEnvironmentWindowsNt
343 * ProcessorType - returns NdisProcessorX86 until more architectures are added
344 * NdisVersion - returns NDIS_VERSION
345 * ParameterType: the type of the value to be queried
346 * RETURNS:
347 * - A status in Status
348 * - A parameter value in ParameterValue
349 */
350 {
351 KEY_VALUE_PARTIAL_INFORMATION *KeyInformation;
352 ULONG KeyDataLength;
353 PMINIPORT_RESOURCE MiniportResource;
354 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext = (PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle;
355 PVOID Buffer;
356
357 *ParameterValue = NULL;
358 *Status = NDIS_STATUS_FAILURE;
359
360 NDIS_DbgPrint(MAX_TRACE,("requested read of %wZ\n", Keyword));
361
362 if (ConfigurationContext == NULL)
363 {
364 NDIS_DbgPrint(MIN_TRACE,("invalid parameter ConfigurationContext (0x%x)\n",ConfigurationContext));
365 return;
366 }
367
368 if(
369 !wcsncmp(Keyword->Buffer, L"Environment", Keyword->Length/sizeof(WCHAR)) &&
370 wcslen(L"Environment") == Keyword->Length/sizeof(WCHAR)
371 )
372 {
373 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
374 if(!*ParameterValue)
375 {
376 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
377 *Status = NDIS_STATUS_RESOURCES;
378 return;
379 }
380
381 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
382 if(!MiniportResource)
383 {
384 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
385 ExFreePool(*ParameterValue);
386 *ParameterValue = NULL;
387 *Status = NDIS_STATUS_RESOURCES;
388 return;
389 }
390
391 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
392 MiniportResource->Resource = *ParameterValue;
393
394 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n",
395 MiniportResource->Resource));
396
397 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
398 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
399
400 (*ParameterValue)->ParameterType = NdisParameterInteger;
401 (*ParameterValue)->ParameterData.IntegerData = NdisEnvironmentWindowsNt;
402 *Status = NDIS_STATUS_SUCCESS;
403
404 return;
405 }
406
407 if(
408 !wcsncmp(Keyword->Buffer, L"ProcessorType", Keyword->Length/sizeof(WCHAR)) &&
409 wcslen(L"ProcessorType") == Keyword->Length/sizeof(WCHAR)
410 )
411 {
412 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
413 if(!*ParameterValue)
414 {
415 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
416 *Status = NDIS_STATUS_RESOURCES;
417 return;
418 }
419
420 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
421 if(!MiniportResource)
422 {
423 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
424 ExFreePool(*ParameterValue);
425 *ParameterValue = NULL;
426 *Status = NDIS_STATUS_RESOURCES;
427 return;
428 }
429
430 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
431 MiniportResource->Resource = *ParameterValue;
432 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
433 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
434 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
435
436 (*ParameterValue)->ParameterType = NdisParameterInteger;
437 (*ParameterValue)->ParameterData.IntegerData = NdisProcessorX86; /* XXX non-portable */
438 *Status = NDIS_STATUS_SUCCESS;
439
440 return;
441 }
442
443 if(
444 !wcsncmp(Keyword->Buffer, L"NdisVersion", Keyword->Length/sizeof(WCHAR)) &&
445 wcslen(L"NdisVersion") == Keyword->Length/sizeof(WCHAR)
446 )
447 {
448 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
449 if(!*ParameterValue)
450 {
451 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
452 *Status = NDIS_STATUS_RESOURCES;
453 return;
454 }
455
456 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
457 if(!MiniportResource)
458 {
459 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
460 ExFreePool(*ParameterValue);
461 *ParameterValue = NULL;
462 *Status = NDIS_STATUS_RESOURCES;
463 return;
464 }
465
466 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
467 MiniportResource->Resource = *ParameterValue;
468 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
469 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
470 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
471
472 (*ParameterValue)->ParameterType = NdisParameterInteger;
473 (*ParameterValue)->ParameterData.IntegerData = NDIS_VERSION;
474 *Status = NDIS_STATUS_SUCCESS;
475
476 NDIS_DbgPrint(MAX_TRACE,("ParameterType = %0x%x, ParameterValue = 0x%x\n",
477 (*ParameterValue)->ParameterType, (*ParameterValue)->ParameterData.IntegerData));
478 return;
479 }
480
481 /* figure out how much buffer i should allocate */
482 *Status = ZwQueryValueKey(ConfigurationContext->Handle, Keyword, KeyValuePartialInformation, NULL, 0, &KeyDataLength);
483 if(*Status != STATUS_BUFFER_OVERFLOW && *Status != STATUS_BUFFER_TOO_SMALL && *Status != STATUS_SUCCESS)
484 {
485 NDIS_DbgPrint(MID_TRACE,("ZwQueryValueKey #1 failed for %wZ, status 0x%x\n", Keyword, *Status));
486 *Status = NDIS_STATUS_FAILURE;
487 return;
488 }
489
490 /* allocate it */
491 KeyInformation = ExAllocatePool(PagedPool, KeyDataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION));
492 if(!KeyInformation)
493 {
494 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
495 *Status = NDIS_STATUS_RESOURCES;
496 return;
497 }
498
499 /* grab the value */
500 *Status = ZwQueryValueKey(ConfigurationContext->Handle, Keyword, KeyValuePartialInformation,
501 KeyInformation, KeyDataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION), &KeyDataLength);
502 if(*Status != STATUS_SUCCESS)
503 {
504 ExFreePool(KeyInformation);
505 NDIS_DbgPrint(MIN_TRACE,("ZwQueryValueKey #2 failed for %wZ, status 0x%x\n", Keyword, *Status));
506 *Status = NDIS_STATUS_FAILURE;
507 return;
508 }
509
510 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
511 if(!MiniportResource)
512 {
513 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
514 ExFreePool(KeyInformation);
515 *Status = NDIS_STATUS_RESOURCES;
516 return;
517 }
518
519 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
520 if (!*ParameterValue)
521 {
522 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
523 ExFreePool(MiniportResource);
524 ExFreePool(KeyInformation);
525 *Status = NDIS_STATUS_RESOURCES;
526 return;
527 }
528
529 RtlZeroMemory(*ParameterValue, sizeof(NDIS_CONFIGURATION_PARAMETER));
530
531 if (KeyInformation->Type == REG_BINARY)
532 {
533 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterBinary\n"));
534
535 (*ParameterValue)->ParameterType = NdisParameterBinary;
536
537 Buffer = ExAllocatePool(NonPagedPool, KeyInformation->DataLength);
538 if (!Buffer)
539 {
540 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
541 ExFreePool(MiniportResource);
542 ExFreePool(KeyInformation);
543 *Status = NDIS_STATUS_RESOURCES;
544 return;
545 }
546
547 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
548
549 (*ParameterValue)->ParameterData.BinaryData.Buffer = Buffer;
550 (*ParameterValue)->ParameterData.BinaryData.Length = KeyInformation->DataLength;
551 }
552 else if (KeyInformation->Type == REG_MULTI_SZ)
553 {
554 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterMultiString\n"));
555
556 (*ParameterValue)->ParameterType = NdisParameterMultiString;
557
558 Buffer = ExAllocatePool(NonPagedPool, KeyInformation->DataLength);
559 if (!Buffer)
560 {
561 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
562 ExFreePool(MiniportResource);
563 ExFreePool(KeyInformation);
564 *Status = NDIS_STATUS_RESOURCES;
565 return;
566 }
567
568 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
569
570 (*ParameterValue)->ParameterData.StringData.Buffer = Buffer;
571 (*ParameterValue)->ParameterData.StringData.Length = KeyInformation->DataLength;
572 }
573 else
574 {
575 UNICODE_STRING str;
576
577 str.Length = str.MaximumLength = (USHORT)KeyInformation->DataLength;
578 str.Buffer = (PWCHAR)KeyInformation->Data;
579
580 if ((*Status = RtlUnicodeStringToInteger(&str, 0,
581 &(*ParameterValue)->ParameterData.IntegerData)) == STATUS_SUCCESS)
582 {
583 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterInteger\n"));
584
585 (*ParameterValue)->ParameterType = NdisParameterInteger;
586 }
587 else
588 {
589 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterString\n"));
590
591 (*ParameterValue)->ParameterType = NdisParameterString;
592
593 Buffer = ExAllocatePool(NonPagedPool, KeyInformation->DataLength);
594 if (!Buffer)
595 {
596 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
597 ExFreePool(MiniportResource);
598 ExFreePool(KeyInformation);
599 *Status = NDIS_STATUS_RESOURCES;
600 return;
601 }
602
603 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
604
605 (*ParameterValue)->ParameterData.StringData.Buffer = Buffer;
606 (*ParameterValue)->ParameterData.StringData.Length = KeyInformation->DataLength;
607 }
608 }
609
610 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
611 MiniportResource->Resource = *ParameterValue;
612
613 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
614
615 ExFreePool(KeyInformation);
616
617 *Status = NDIS_STATUS_SUCCESS;
618 }
619
620
621 UCHAR UnicodeToHexByte(WCHAR chr)
622 /*
623 * FUNCTION: Converts a unicode hex character to its numerical value
624 * ARGUMENTS:
625 * chr: Unicode character to convert
626 * RETURNS:
627 * The numerical value of chr
628 */
629 {
630 switch(chr)
631 {
632 case L'0': return 0;
633 case L'1': return 1;
634 case L'2': return 2;
635 case L'3': return 3;
636 case L'4': return 4;
637 case L'5': return 5;
638 case L'6': return 6;
639 case L'7': return 7;
640 case L'8': return 8;
641 case L'9': return 9;
642 case L'A':
643 case L'a':
644 return 10;
645 case L'B':
646 case L'b':
647 return 11;
648 case L'C':
649 case L'c':
650 return 12;
651 case L'D':
652 case L'd':
653 return 13;
654 case L'E':
655 case L'e':
656 return 14;
657 case L'F':
658 case L'f':
659 return 15;
660 }
661 return -1;
662 }
663
664
665 /*
666 * @implemented
667 */
668 VOID
669 EXPORT
670 NdisReadNetworkAddress(
671 OUT PNDIS_STATUS Status,
672 OUT PVOID * NetworkAddress,
673 OUT PUINT NetworkAddressLength,
674 IN NDIS_HANDLE ConfigurationHandle)
675 /*
676 * FUNCTION: Reads the network address from the registry
677 * ARGUMENTS:
678 * Status - variable to receive status
679 * NetworkAddress - pointer to a buffered network address array
680 * NetworkAddressLength - length of the NetworkAddress array
681 * ConfigurationHandle: handle passed back from one of the open routines
682 * RETURNS:
683 * NDIS_STATUS_SUCCESS on success
684 * NDIS_STATUS_FAILURE on failure
685 * The network address is placed in the NetworkAddress buffer
686 */
687 {
688 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext = (PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle;
689 PMINIPORT_RESOURCE MiniportResource = NULL;
690 PNDIS_CONFIGURATION_PARAMETER ParameterValue = NULL;
691 NDIS_STRING Keyword;
692 UINT *IntArray = 0;
693 UINT i,j = 0;
694 NDIS_STRING str;
695
696 NdisInitUnicodeString(&Keyword, L"NetworkAddress");
697 NdisReadConfiguration(Status, &ParameterValue, ConfigurationHandle, &Keyword, NdisParameterString);
698 if(*Status != NDIS_STATUS_SUCCESS)
699 {
700 NDIS_DbgPrint(MID_TRACE, ("NdisReadConfiguration failed (%x)\n", *Status));
701 *Status = NDIS_STATUS_FAILURE;
702 return;
703 }
704
705 if (ParameterValue->ParameterType == NdisParameterInteger)
706 {
707 WCHAR Buff[11];
708
709 NDIS_DbgPrint(MAX_TRACE, ("Read integer data %lx\n",
710 ParameterValue->ParameterData.IntegerData));
711
712 str.Buffer = Buff;
713 str.MaximumLength = (USHORT)sizeof(Buff);
714 str.Length = 0;
715
716 *Status = RtlIntegerToUnicodeString(ParameterValue->ParameterData.IntegerData,
717 10,
718 &str);
719
720 if (*Status != NDIS_STATUS_SUCCESS)
721 {
722 NDIS_DbgPrint(MIN_TRACE, ("RtlIntegerToUnicodeString failed (%x)\n", *Status));
723 *Status = NDIS_STATUS_FAILURE;
724 return;
725 }
726
727 NDIS_DbgPrint(MAX_TRACE, ("Converted integer data into %wZ\n", &str));
728 }
729 else
730 {
731 ASSERT(ParameterValue->ParameterType == NdisParameterString);
732 str = ParameterValue->ParameterData.StringData;
733 }
734
735 while (j < str.Length && str.Buffer[j] != '\0') j++;
736
737 *NetworkAddressLength = (j+1) >> 1;
738
739 if ((*NetworkAddressLength) == 0)
740 {
741 NDIS_DbgPrint(MIN_TRACE,("Empty NetworkAddress registry entry.\n"));
742 *Status = NDIS_STATUS_FAILURE;
743 return;
744 }
745
746 IntArray = ExAllocatePool(PagedPool, (*NetworkAddressLength)*sizeof(UINT));
747 if(!IntArray)
748 {
749 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
750 *Status = NDIS_STATUS_RESOURCES;
751 return;
752 }
753
754 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
755 if(!MiniportResource)
756 {
757 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
758 ExFreePool(IntArray);
759 *Status = NDIS_STATUS_RESOURCES;
760 return;
761 }
762
763 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_MEMORY;
764 MiniportResource->Resource = IntArray;
765 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
766 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
767
768 /* convert from string to bytes */
769 for(i=0; i<(*NetworkAddressLength); i++)
770 {
771 IntArray[i] = (UnicodeToHexByte((str.Buffer)[2*i]) << 4) +
772 UnicodeToHexByte((str.Buffer)[2*i+1]);
773 }
774
775 *NetworkAddress = IntArray;
776
777 *Status = NDIS_STATUS_SUCCESS;
778 }
779
780
781 /*
782 * @implemented
783 */
784 VOID
785 EXPORT
786 NdisOpenConfigurationKeyByIndex(
787 OUT PNDIS_STATUS Status,
788 IN NDIS_HANDLE ConfigurationHandle,
789 IN ULONG Index,
790 OUT PNDIS_STRING KeyName,
791 OUT PNDIS_HANDLE KeyHandle)
792 /*
793 * FUNCTION: Opens a configuration subkey by index number
794 * ARGUMENTS:
795 * Status: pointer to an NDIS_STATUS to receive status info
796 * ConfigurationHandle: the handle passed back from a previous open function
797 * Index: the zero-based index of the subkey to open
798 * KeyName: the name of the key that was opened
799 * KeyHandle: a handle to the key that was opened
800 * RETURNS:
801 * NDIS_STATUS_SUCCESS on success
802 * NDIS_STATUS_FAILURE on failure
803 * KeyName holds the name of the opened key
804 * KeyHandle holds a handle to the new key
805 */
806 {
807 KEY_BASIC_INFORMATION *KeyInformation;
808 ULONG KeyInformationLength;
809 OBJECT_ATTRIBUTES KeyAttributes;
810 NDIS_HANDLE RegKeyHandle;
811 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
812
813 *KeyHandle = NULL;
814
815 *Status = ZwEnumerateKey(ConfigurationHandle, Index, KeyBasicInformation, NULL, 0, &KeyInformationLength);
816 if(*Status != STATUS_BUFFER_TOO_SMALL && *Status != STATUS_BUFFER_OVERFLOW && *Status != STATUS_SUCCESS)
817 {
818 NDIS_DbgPrint(MIN_TRACE, ("ZwEnumerateKey failed (%x)\n", *Status));
819 *Status = NDIS_STATUS_FAILURE;
820 return;
821 }
822
823 KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength + sizeof(KEY_BASIC_INFORMATION));
824 if(!KeyInformation)
825 {
826 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
827 *Status = NDIS_STATUS_FAILURE;
828 return;
829 }
830
831 *Status = ZwEnumerateKey(ConfigurationHandle, Index, KeyBasicInformation, KeyInformation,
832 KeyInformationLength + sizeof(KEY_BASIC_INFORMATION), &KeyInformationLength);
833
834 if(*Status != STATUS_SUCCESS)
835 {
836 NDIS_DbgPrint(MIN_TRACE, ("ZwEnumerateKey failed (%x)\n", *Status));
837 ExFreePool(KeyInformation);
838 *Status = NDIS_STATUS_FAILURE;
839 return;
840 }
841
842 /* should i fail instead if the passed-in string isn't long enough? */
843 wcsncpy(KeyName->Buffer, KeyInformation->Name, KeyName->MaximumLength/sizeof(WCHAR));
844 KeyName->Length = (USHORT)min(KeyInformation->NameLength, KeyName->MaximumLength);
845
846 InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE, ConfigurationHandle, NULL);
847
848 *Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
849
850 ExFreePool(KeyInformation);
851
852 if(*Status != STATUS_SUCCESS)
853 {
854 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
855 *Status = NDIS_STATUS_FAILURE;
856 return;
857 }
858
859 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
860 if(!ConfigurationContext)
861 {
862 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
863 ZwClose(RegKeyHandle);
864 *Status = NDIS_STATUS_FAILURE;
865 return;
866 }
867
868 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
869 InitializeListHead(&ConfigurationContext->ResourceListHead);
870
871 ConfigurationContext->Handle = RegKeyHandle;
872
873 *KeyHandle = (NDIS_HANDLE)ConfigurationContext;
874
875 *Status = NDIS_STATUS_SUCCESS;
876 }
877
878
879 /*
880 * @implemented
881 */
882 VOID
883 EXPORT
884 NdisOpenConfigurationKeyByName(
885 OUT PNDIS_STATUS Status,
886 IN NDIS_HANDLE ConfigurationHandle,
887 IN PNDIS_STRING KeyName,
888 OUT PNDIS_HANDLE KeyHandle)
889 /*
890 * FUNCTION: Opens a configuration subkey by name
891 * ARGUMENTS:
892 * Status: points to an NDIS_STATUS where status is returned
893 * ConfigurationHandle: handle returned by a previous open call
894 * KeyName: the name of the key to open
895 * KeyHandle: a handle to the opened key
896 * RETURNS:
897 * NDIS_STATUS_SUCCESS on success
898 * NDIS_STATUS_FAILURE on failure
899 * KeyHandle holds a handle to the newly-opened key
900 * NOTES:
901 */
902 {
903 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
904 OBJECT_ATTRIBUTES KeyAttributes;
905 NDIS_HANDLE RegKeyHandle;
906
907 *KeyHandle = NULL;
908
909 InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE, ConfigurationHandle, 0);
910 *Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
911
912 if(*Status != STATUS_SUCCESS)
913 {
914 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
915 *Status = NDIS_STATUS_FAILURE;
916 return;
917 }
918
919 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
920 if(!ConfigurationContext)
921 {
922 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
923 ZwClose(RegKeyHandle);
924 *Status = NDIS_STATUS_FAILURE;
925 return;
926 }
927
928 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
929 InitializeListHead(&ConfigurationContext->ResourceListHead);
930
931 ConfigurationContext->Handle = RegKeyHandle;
932
933 *KeyHandle = (NDIS_HANDLE)ConfigurationContext;
934
935 *Status = NDIS_STATUS_SUCCESS;
936 }