6aea7dfa79c1008fe595c60a3e3ae5b55a698895
[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 UCHAR UnicodeToHexByte(WCHAR chr)
324 /*
325 * FUNCTION: Converts a unicode hex character to its numerical value
326 * ARGUMENTS:
327 * chr: Unicode character to convert
328 * RETURNS:
329 * The numerical value of chr
330 */
331 {
332 switch(chr)
333 {
334 case L'0': return 0;
335 case L'1': return 1;
336 case L'2': return 2;
337 case L'3': return 3;
338 case L'4': return 4;
339 case L'5': return 5;
340 case L'6': return 6;
341 case L'7': return 7;
342 case L'8': return 8;
343 case L'9': return 9;
344 case L'A':
345 case L'a':
346 return 10;
347 case L'B':
348 case L'b':
349 return 11;
350 case L'C':
351 case L'c':
352 return 12;
353 case L'D':
354 case L'd':
355 return 13;
356 case L'E':
357 case L'e':
358 return 14;
359 case L'F':
360 case L'f':
361 return 15;
362 }
363 return 0xFF;
364 }
365
366 BOOLEAN
367 IsValidNumericString(PNDIS_STRING String, NDIS_PARAMETER_TYPE *ParameterType)
368 /*
369 * FUNCTION: Determines if a string is a valid number
370 * ARGUMENTS:
371 * String: Unicode string to evaluate
372 * RETURNS:
373 * TRUE if it is valid, FALSE if not
374 */
375 {
376 ULONG i;
377
378 /* I don't think this will ever happen, but we warn it if it does */
379 if (String->Length == 0)
380 {
381 NDIS_DbgPrint(MIN_TRACE, ("Got an empty string; not sure what to do here\n"));
382 return FALSE;
383 }
384
385 /* Set the default parameter type */
386 *ParameterType = NdisParameterInteger;
387
388 for (i = 0; i < String->Length / sizeof(WCHAR); i++)
389 {
390 /* Look at the second character for the base */
391 if (i == 1)
392 {
393 if (String->Buffer[i] == L'X' ||
394 String->Buffer[i] == L'x')
395 {
396 NDIS_DbgPrint(MID_TRACE, ("Identified hex string\n"));
397 *ParameterType = NdisParameterHexInteger;
398 continue;
399 }
400 }
401
402 /* Skip any NULL characters we find */
403 if (String->Buffer[i] == UNICODE_NULL)
404 continue;
405
406 /* Make sure the character is valid for a numeric string */
407 if (UnicodeToHexByte(String->Buffer[i]) == 0xFF)
408 return FALSE;
409 }
410
411 /* It's valid */
412 return TRUE;
413 }
414
415 /*
416 * @implemented
417 */
418 VOID
419 EXPORT
420 NdisReadConfiguration(
421 OUT PNDIS_STATUS Status,
422 OUT PNDIS_CONFIGURATION_PARAMETER * ParameterValue,
423 IN NDIS_HANDLE ConfigurationHandle,
424 IN PNDIS_STRING Keyword,
425 IN NDIS_PARAMETER_TYPE ParameterType)
426 /*
427 * FUNCTION: Read a configuration value from the registry, tracking its resources
428 * ARGUMENTS:
429 * Status: points to a place to write status into
430 * ParameterValue: Pointer to receive a newly-allocated parameter structure
431 * ConfigurationHandle: handle originally returned by an open function
432 * Keyword: Value name to read, or one of the following constants:
433 * Environment - returns NdisEnvironmentWindowsNt
434 * ProcessorType - returns NdisProcessorX86 until more architectures are added
435 * NdisVersion - returns NDIS_VERSION
436 * ParameterType: the type of the value to be queried
437 * RETURNS:
438 * - A status in Status
439 * - A parameter value in ParameterValue
440 */
441 {
442 KEY_VALUE_PARTIAL_INFORMATION *KeyInformation;
443 ULONG KeyDataLength;
444 PMINIPORT_RESOURCE MiniportResource;
445 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext = (PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle;
446 PVOID Buffer;
447
448 *ParameterValue = NULL;
449 *Status = NDIS_STATUS_FAILURE;
450
451 NDIS_DbgPrint(MAX_TRACE,("requested read of %wZ\n", Keyword));
452
453 if (ConfigurationContext == NULL)
454 {
455 NDIS_DbgPrint(MIN_TRACE,("invalid parameter ConfigurationContext (0x%x)\n",ConfigurationContext));
456 return;
457 }
458
459 if(
460 !wcsncmp(Keyword->Buffer, L"Environment", Keyword->Length/sizeof(WCHAR)) &&
461 wcslen(L"Environment") == Keyword->Length/sizeof(WCHAR)
462 )
463 {
464 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
465 if(!*ParameterValue)
466 {
467 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
468 *Status = NDIS_STATUS_RESOURCES;
469 return;
470 }
471
472 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
473 if(!MiniportResource)
474 {
475 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
476 ExFreePool(*ParameterValue);
477 *ParameterValue = NULL;
478 *Status = NDIS_STATUS_RESOURCES;
479 return;
480 }
481
482 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
483 MiniportResource->Resource = *ParameterValue;
484
485 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n",
486 MiniportResource->Resource));
487
488 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
489 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
490
491 (*ParameterValue)->ParameterType = NdisParameterInteger;
492 (*ParameterValue)->ParameterData.IntegerData = NdisEnvironmentWindowsNt;
493 *Status = NDIS_STATUS_SUCCESS;
494
495 return;
496 }
497
498 if(
499 !wcsncmp(Keyword->Buffer, L"ProcessorType", Keyword->Length/sizeof(WCHAR)) &&
500 wcslen(L"ProcessorType") == Keyword->Length/sizeof(WCHAR)
501 )
502 {
503 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
504 if(!*ParameterValue)
505 {
506 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
507 *Status = NDIS_STATUS_RESOURCES;
508 return;
509 }
510
511 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
512 if(!MiniportResource)
513 {
514 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
515 ExFreePool(*ParameterValue);
516 *ParameterValue = NULL;
517 *Status = NDIS_STATUS_RESOURCES;
518 return;
519 }
520
521 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
522 MiniportResource->Resource = *ParameterValue;
523 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
524 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
525 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
526
527 (*ParameterValue)->ParameterType = NdisParameterInteger;
528 (*ParameterValue)->ParameterData.IntegerData = NdisProcessorX86; /* XXX non-portable */
529 *Status = NDIS_STATUS_SUCCESS;
530
531 return;
532 }
533
534 if(
535 !wcsncmp(Keyword->Buffer, L"NdisVersion", Keyword->Length/sizeof(WCHAR)) &&
536 wcslen(L"NdisVersion") == Keyword->Length/sizeof(WCHAR)
537 )
538 {
539 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
540 if(!*ParameterValue)
541 {
542 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
543 *Status = NDIS_STATUS_RESOURCES;
544 return;
545 }
546
547 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
548 if(!MiniportResource)
549 {
550 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
551 ExFreePool(*ParameterValue);
552 *ParameterValue = NULL;
553 *Status = NDIS_STATUS_RESOURCES;
554 return;
555 }
556
557 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
558 MiniportResource->Resource = *ParameterValue;
559 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
560 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
561 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
562
563 (*ParameterValue)->ParameterType = NdisParameterInteger;
564 (*ParameterValue)->ParameterData.IntegerData = NDIS_VERSION;
565 *Status = NDIS_STATUS_SUCCESS;
566
567 NDIS_DbgPrint(MAX_TRACE,("ParameterType = %0x%x, ParameterValue = 0x%x\n",
568 (*ParameterValue)->ParameterType, (*ParameterValue)->ParameterData.IntegerData));
569 return;
570 }
571
572 /* figure out how much buffer i should allocate */
573 *Status = ZwQueryValueKey(ConfigurationContext->Handle, Keyword, KeyValuePartialInformation, NULL, 0, &KeyDataLength);
574 if(*Status != STATUS_BUFFER_OVERFLOW && *Status != STATUS_BUFFER_TOO_SMALL && *Status != STATUS_SUCCESS)
575 {
576 NDIS_DbgPrint(MID_TRACE,("ZwQueryValueKey #1 failed for %wZ, status 0x%x\n", Keyword, *Status));
577 *Status = NDIS_STATUS_FAILURE;
578 return;
579 }
580
581 /* allocate it */
582 KeyInformation = ExAllocatePool(PagedPool, KeyDataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION));
583 if(!KeyInformation)
584 {
585 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
586 *Status = NDIS_STATUS_RESOURCES;
587 return;
588 }
589
590 /* grab the value */
591 *Status = ZwQueryValueKey(ConfigurationContext->Handle, Keyword, KeyValuePartialInformation,
592 KeyInformation, KeyDataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION), &KeyDataLength);
593 if(*Status != STATUS_SUCCESS)
594 {
595 ExFreePool(KeyInformation);
596 NDIS_DbgPrint(MIN_TRACE,("ZwQueryValueKey #2 failed for %wZ, status 0x%x\n", Keyword, *Status));
597 *Status = NDIS_STATUS_FAILURE;
598 return;
599 }
600
601 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
602 if(!MiniportResource)
603 {
604 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
605 ExFreePool(KeyInformation);
606 *Status = NDIS_STATUS_RESOURCES;
607 return;
608 }
609
610 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
611 if (!*ParameterValue)
612 {
613 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
614 ExFreePool(MiniportResource);
615 ExFreePool(KeyInformation);
616 *Status = NDIS_STATUS_RESOURCES;
617 return;
618 }
619
620 RtlZeroMemory(*ParameterValue, sizeof(NDIS_CONFIGURATION_PARAMETER));
621
622 if (KeyInformation->Type == REG_BINARY)
623 {
624 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterBinary\n"));
625
626 (*ParameterValue)->ParameterType = NdisParameterBinary;
627
628 Buffer = ExAllocatePool(NonPagedPool, KeyInformation->DataLength);
629 if (!Buffer)
630 {
631 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
632 ExFreePool(MiniportResource);
633 ExFreePool(KeyInformation);
634 *Status = NDIS_STATUS_RESOURCES;
635 return;
636 }
637
638 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
639
640 (*ParameterValue)->ParameterData.BinaryData.Buffer = Buffer;
641 (*ParameterValue)->ParameterData.BinaryData.Length = KeyInformation->DataLength;
642 }
643 else if (KeyInformation->Type == REG_MULTI_SZ)
644 {
645 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterMultiString\n"));
646
647 (*ParameterValue)->ParameterType = NdisParameterMultiString;
648
649 Buffer = ExAllocatePool(NonPagedPool, KeyInformation->DataLength);
650 if (!Buffer)
651 {
652 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
653 ExFreePool(MiniportResource);
654 ExFreePool(KeyInformation);
655 *Status = NDIS_STATUS_RESOURCES;
656 return;
657 }
658
659 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
660
661 (*ParameterValue)->ParameterData.StringData.Buffer = Buffer;
662 (*ParameterValue)->ParameterData.StringData.Length = KeyInformation->DataLength;
663 }
664 else
665 {
666 UNICODE_STRING str;
667
668 str.Length = str.MaximumLength = (USHORT)KeyInformation->DataLength;
669 str.Buffer = (PWCHAR)KeyInformation->Data;
670
671 if (IsValidNumericString(&str, &(*ParameterValue)->ParameterType) &&
672 ((*Status = RtlUnicodeStringToInteger(&str, 0,
673 &(*ParameterValue)->ParameterData.IntegerData)) == STATUS_SUCCESS))
674 {
675 NDIS_DbgPrint(MAX_TRACE, ("NdisParameter(Hex)Integer\n"));
676
677 /* IsValidNumericString sets the parameter type when parsing the string */
678 }
679 else
680 {
681 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterString\n"));
682
683 (*ParameterValue)->ParameterType = NdisParameterString;
684
685 Buffer = ExAllocatePool(NonPagedPool, KeyInformation->DataLength);
686 if (!Buffer)
687 {
688 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
689 ExFreePool(MiniportResource);
690 ExFreePool(KeyInformation);
691 *Status = NDIS_STATUS_RESOURCES;
692 return;
693 }
694
695 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
696
697 (*ParameterValue)->ParameterData.StringData.Buffer = Buffer;
698 (*ParameterValue)->ParameterData.StringData.Length = KeyInformation->DataLength;
699 }
700 }
701
702 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
703 MiniportResource->Resource = *ParameterValue;
704
705 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
706
707 ExFreePool(KeyInformation);
708
709 *Status = NDIS_STATUS_SUCCESS;
710 }
711
712 /*
713 * @implemented
714 */
715 VOID
716 EXPORT
717 NdisReadNetworkAddress(
718 OUT PNDIS_STATUS Status,
719 OUT PVOID * NetworkAddress,
720 OUT PUINT NetworkAddressLength,
721 IN NDIS_HANDLE ConfigurationHandle)
722 /*
723 * FUNCTION: Reads the network address from the registry
724 * ARGUMENTS:
725 * Status - variable to receive status
726 * NetworkAddress - pointer to a buffered network address array
727 * NetworkAddressLength - length of the NetworkAddress array
728 * ConfigurationHandle: handle passed back from one of the open routines
729 * RETURNS:
730 * NDIS_STATUS_SUCCESS on success
731 * NDIS_STATUS_FAILURE on failure
732 * The network address is placed in the NetworkAddress buffer
733 */
734 {
735 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext = (PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle;
736 PMINIPORT_RESOURCE MiniportResource = NULL;
737 PNDIS_CONFIGURATION_PARAMETER ParameterValue = NULL;
738 NDIS_STRING Keyword;
739 UINT *IntArray = 0;
740 UINT i,j = 0;
741 NDIS_STRING str;
742
743 NdisInitUnicodeString(&Keyword, L"NetworkAddress");
744 NdisReadConfiguration(Status, &ParameterValue, ConfigurationHandle, &Keyword, NdisParameterString);
745 if(*Status != NDIS_STATUS_SUCCESS)
746 {
747 NDIS_DbgPrint(MID_TRACE, ("NdisReadConfiguration failed (%x)\n", *Status));
748 *Status = NDIS_STATUS_FAILURE;
749 return;
750 }
751
752 if (ParameterValue->ParameterType == NdisParameterInteger)
753 {
754 WCHAR Buff[11];
755
756 NDIS_DbgPrint(MAX_TRACE, ("Read integer data %lx\n",
757 ParameterValue->ParameterData.IntegerData));
758
759 str.Buffer = Buff;
760 str.MaximumLength = (USHORT)sizeof(Buff);
761 str.Length = 0;
762
763 *Status = RtlIntegerToUnicodeString(ParameterValue->ParameterData.IntegerData,
764 10,
765 &str);
766
767 if (*Status != NDIS_STATUS_SUCCESS)
768 {
769 NDIS_DbgPrint(MIN_TRACE, ("RtlIntegerToUnicodeString failed (%x)\n", *Status));
770 *Status = NDIS_STATUS_FAILURE;
771 return;
772 }
773
774 NDIS_DbgPrint(MAX_TRACE, ("Converted integer data into %wZ\n", &str));
775 }
776 else
777 {
778 ASSERT(ParameterValue->ParameterType == NdisParameterString);
779 str = ParameterValue->ParameterData.StringData;
780 }
781
782 while (j < str.Length && str.Buffer[j] != '\0') j++;
783
784 *NetworkAddressLength = (j+1) >> 1;
785
786 if ((*NetworkAddressLength) == 0)
787 {
788 NDIS_DbgPrint(MIN_TRACE,("Empty NetworkAddress registry entry.\n"));
789 *Status = NDIS_STATUS_FAILURE;
790 return;
791 }
792
793 IntArray = ExAllocatePool(PagedPool, (*NetworkAddressLength)*sizeof(UINT));
794 if(!IntArray)
795 {
796 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
797 *Status = NDIS_STATUS_RESOURCES;
798 return;
799 }
800
801 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
802 if(!MiniportResource)
803 {
804 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
805 ExFreePool(IntArray);
806 *Status = NDIS_STATUS_RESOURCES;
807 return;
808 }
809
810 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_MEMORY;
811 MiniportResource->Resource = IntArray;
812 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
813 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
814
815 /* convert from string to bytes */
816 for(i=0; i<(*NetworkAddressLength); i++)
817 {
818 IntArray[i] = (UnicodeToHexByte((str.Buffer)[2*i]) << 4) +
819 UnicodeToHexByte((str.Buffer)[2*i+1]);
820 }
821
822 *NetworkAddress = IntArray;
823
824 *Status = NDIS_STATUS_SUCCESS;
825 }
826
827
828 /*
829 * @implemented
830 */
831 VOID
832 EXPORT
833 NdisOpenConfigurationKeyByIndex(
834 OUT PNDIS_STATUS Status,
835 IN NDIS_HANDLE ConfigurationHandle,
836 IN ULONG Index,
837 OUT PNDIS_STRING KeyName,
838 OUT PNDIS_HANDLE KeyHandle)
839 /*
840 * FUNCTION: Opens a configuration subkey by index number
841 * ARGUMENTS:
842 * Status: pointer to an NDIS_STATUS to receive status info
843 * ConfigurationHandle: the handle passed back from a previous open function
844 * Index: the zero-based index of the subkey to open
845 * KeyName: the name of the key that was opened
846 * KeyHandle: a handle to the key that was opened
847 * RETURNS:
848 * NDIS_STATUS_SUCCESS on success
849 * NDIS_STATUS_FAILURE on failure
850 * KeyName holds the name of the opened key
851 * KeyHandle holds a handle to the new key
852 */
853 {
854 KEY_BASIC_INFORMATION *KeyInformation;
855 ULONG KeyInformationLength;
856 OBJECT_ATTRIBUTES KeyAttributes;
857 NDIS_HANDLE RegKeyHandle;
858 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
859
860 *KeyHandle = NULL;
861
862 *Status = ZwEnumerateKey(ConfigurationHandle, Index, KeyBasicInformation, NULL, 0, &KeyInformationLength);
863 if(*Status != STATUS_BUFFER_TOO_SMALL && *Status != STATUS_BUFFER_OVERFLOW && *Status != STATUS_SUCCESS)
864 {
865 NDIS_DbgPrint(MIN_TRACE, ("ZwEnumerateKey failed (%x)\n", *Status));
866 *Status = NDIS_STATUS_FAILURE;
867 return;
868 }
869
870 KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength + sizeof(KEY_BASIC_INFORMATION));
871 if(!KeyInformation)
872 {
873 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
874 *Status = NDIS_STATUS_FAILURE;
875 return;
876 }
877
878 *Status = ZwEnumerateKey(ConfigurationHandle, Index, KeyBasicInformation, KeyInformation,
879 KeyInformationLength + sizeof(KEY_BASIC_INFORMATION), &KeyInformationLength);
880
881 if(*Status != STATUS_SUCCESS)
882 {
883 NDIS_DbgPrint(MIN_TRACE, ("ZwEnumerateKey failed (%x)\n", *Status));
884 ExFreePool(KeyInformation);
885 *Status = NDIS_STATUS_FAILURE;
886 return;
887 }
888
889 /* should i fail instead if the passed-in string isn't long enough? */
890 wcsncpy(KeyName->Buffer, KeyInformation->Name, KeyName->MaximumLength/sizeof(WCHAR));
891 KeyName->Length = (USHORT)min(KeyInformation->NameLength, KeyName->MaximumLength);
892
893 InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE, ConfigurationHandle, NULL);
894
895 *Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
896
897 ExFreePool(KeyInformation);
898
899 if(*Status != STATUS_SUCCESS)
900 {
901 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
902 *Status = NDIS_STATUS_FAILURE;
903 return;
904 }
905
906 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
907 if(!ConfigurationContext)
908 {
909 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
910 ZwClose(RegKeyHandle);
911 *Status = NDIS_STATUS_FAILURE;
912 return;
913 }
914
915 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
916 InitializeListHead(&ConfigurationContext->ResourceListHead);
917
918 ConfigurationContext->Handle = RegKeyHandle;
919
920 *KeyHandle = (NDIS_HANDLE)ConfigurationContext;
921
922 *Status = NDIS_STATUS_SUCCESS;
923 }
924
925
926 /*
927 * @implemented
928 */
929 VOID
930 EXPORT
931 NdisOpenConfigurationKeyByName(
932 OUT PNDIS_STATUS Status,
933 IN NDIS_HANDLE ConfigurationHandle,
934 IN PNDIS_STRING KeyName,
935 OUT PNDIS_HANDLE KeyHandle)
936 /*
937 * FUNCTION: Opens a configuration subkey by name
938 * ARGUMENTS:
939 * Status: points to an NDIS_STATUS where status is returned
940 * ConfigurationHandle: handle returned by a previous open call
941 * KeyName: the name of the key to open
942 * KeyHandle: a handle to the opened key
943 * RETURNS:
944 * NDIS_STATUS_SUCCESS on success
945 * NDIS_STATUS_FAILURE on failure
946 * KeyHandle holds a handle to the newly-opened key
947 * NOTES:
948 */
949 {
950 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
951 OBJECT_ATTRIBUTES KeyAttributes;
952 NDIS_HANDLE RegKeyHandle;
953
954 *KeyHandle = NULL;
955
956 InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE, ConfigurationHandle, 0);
957 *Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
958
959 if(*Status != STATUS_SUCCESS)
960 {
961 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
962 *Status = NDIS_STATUS_FAILURE;
963 return;
964 }
965
966 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
967 if(!ConfigurationContext)
968 {
969 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
970 ZwClose(RegKeyHandle);
971 *Status = NDIS_STATUS_FAILURE;
972 return;
973 }
974
975 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
976 InitializeListHead(&ConfigurationContext->ResourceListHead);
977
978 ConfigurationContext->Handle = RegKeyHandle;
979
980 *KeyHandle = (NDIS_HANDLE)ConfigurationContext;
981
982 *Status = NDIS_STATUS_SUCCESS;
983 }