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