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