[NDIS]
[reactos.git] / reactos / drivers / network / ndis / ndis / config.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/config.c
5 * PURPOSE: NDIS Configuration Services
6 * PROGRAMMERS: Vizzini (vizzini@plasmic.com)
7 * REVISIONS:
8 * Vizzini 07-28-2003 Created
9 * NOTES:
10 * - Resource tracking has to be implemented here because of the design of the NDIS API.
11 * Whenever a read operation is performed, the NDIS library allocates space and returns
12 * it. A linked list is kept associated with every handle of the memory allocated to
13 * it. When the handle is closed, the resources are systematically released.
14 * - The NDIS_HANDLE Configuraiton context is no longer a registry handle. An opaque struct
15 * had to be created to allow for resource tracking. This means that Miniports cannot just
16 * pass this NDIS_HANDLE to things like ZwQueryValueKey(). I don't thknk they do (they
17 * certainly should not), but it should be kept in mind.
18 * UPDATE: I just found this in the NTDDK:
19 * NdisOpenProtocolConfiguration returns a handle for the
20 * HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NICDriverInstance\Parameters\ProtocolName
21 * registry key. XXX This is a problem. Following that, the DDK instructs programmers
22 * to use NdisReadConfiguration and NdisWriteConfiguration. No telling what the world's idiots
23 * have done with this.
24 * - I have tried to stick to the DDK's definition of what return values are possible, which
25 * has resulted in stupid return values in some cases. I do use STATUS_RESOURCES in a few
26 * places that the DDK doesn't explicitly mention it, though.
27 * - There's a general reliance on the fact that UNICODE_STRING.Length doesn't include a trailing
28 * 0, which it shouldn't
29 * - I added support for NdisParameterBinary. It's at the end of the struct. I wonder if
30 * it'll break things.
31 * - All the routines in this file are PASSIVE_LEVEL only, and all memory is PagedPool
32 */
33
34 #include "ndissys.h"
35
36 #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 OBJECT_ATTRIBUTES ObjectAttributes;
219 UNICODE_STRING NoName = RTL_CONSTANT_STRING(L"");
220
221 NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
222
223 *ConfigurationHandle = NULL;
224
225 InitializeObjectAttributes(&ObjectAttributes,
226 &NoName,
227 OBJ_KERNEL_HANDLE,
228 RootKeyHandle,
229 NULL);
230 *Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
231 if(!NT_SUCCESS(*Status))
232 {
233 NDIS_DbgPrint(MIN_TRACE, ("Failed to open registry configuration for this miniport\n"));
234 *Status = NDIS_STATUS_FAILURE;
235 return;
236 }
237
238 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
239 if(!ConfigurationContext)
240 {
241 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
242 ZwClose(KeyHandle);
243 *Status = NDIS_STATUS_RESOURCES;
244 return;
245 }
246
247 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
248 InitializeListHead(&ConfigurationContext->ResourceListHead);
249
250 ConfigurationContext->Handle = KeyHandle;
251
252 *ConfigurationHandle = (NDIS_HANDLE)ConfigurationContext;
253 *Status = NDIS_STATUS_SUCCESS;
254
255 NDIS_DbgPrint(MAX_TRACE,("returning success\n"));
256 }
257
258
259 /*
260 * @implemented
261 */
262 VOID
263 EXPORT
264 NdisOpenProtocolConfiguration(
265 OUT PNDIS_STATUS Status,
266 OUT PNDIS_HANDLE ConfigurationHandle,
267 IN PNDIS_STRING ProtocolSection)
268 /*
269 * FUNCTION: Open the configuration key and set up resource tracking for the protocol
270 * ARGUMENTS:
271 * Status: caller-allocated buffer where status is returned
272 * ConfigurationHandle: spot to return the opaque configuration context
273 * ProtocolSection: configuration string originally passed in to ProtocolBindAdapter
274 * RETURNS:
275 * NDIS_STATUS_SUCCESS: the operation was a success
276 * NDIS_STATUS_FAILURE: the operation was not a success
277 * NOTES:
278 * I think this is the per-device (adapter) parameters\{ProtocolName} key; please verify.
279 */
280 {
281 OBJECT_ATTRIBUTES KeyAttributes;
282 UNICODE_STRING KeyNameU;
283 HANDLE KeyHandle;
284 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
285
286 KeyNameU.Length = 0;
287 KeyNameU.MaximumLength = ProtocolSection->Length + sizeof(PARAMETERS_KEY) + sizeof(UNICODE_NULL);
288 KeyNameU.Buffer = ExAllocatePool(PagedPool, KeyNameU.MaximumLength);
289 if(!KeyNameU.Buffer)
290 {
291 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
292 *ConfigurationHandle = NULL;
293 *Status = NDIS_STATUS_FAILURE;
294 return;
295 }
296
297 RtlCopyUnicodeString(&KeyNameU, ProtocolSection);
298 RtlAppendUnicodeToString(&KeyNameU, PARAMETERS_KEY);
299 InitializeObjectAttributes(&KeyAttributes, &KeyNameU, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
300
301 *Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
302
303 ExFreePool(KeyNameU.Buffer);
304
305 if(*Status != NDIS_STATUS_SUCCESS)
306 {
307 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
308 *ConfigurationHandle = NULL;
309 *Status = NDIS_STATUS_FAILURE;
310 return;
311 }
312
313 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
314 if(!ConfigurationContext)
315 {
316 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
317 ZwClose(KeyHandle);
318 *ConfigurationHandle = NULL;
319 *Status = NDIS_STATUS_FAILURE;
320 return;
321 }
322
323 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
324 InitializeListHead(&ConfigurationContext->ResourceListHead);
325
326 ConfigurationContext->Handle = KeyHandle;
327
328 *ConfigurationHandle = (NDIS_HANDLE)ConfigurationContext;
329 *Status = NDIS_STATUS_SUCCESS;
330 }
331
332 UCHAR UnicodeToHexByte(WCHAR chr)
333 /*
334 * FUNCTION: Converts a unicode hex character to its numerical value
335 * ARGUMENTS:
336 * chr: Unicode character to convert
337 * RETURNS:
338 * The numerical value of chr
339 */
340 {
341 switch(chr)
342 {
343 case L'0': return 0;
344 case L'1': return 1;
345 case L'2': return 2;
346 case L'3': return 3;
347 case L'4': return 4;
348 case L'5': return 5;
349 case L'6': return 6;
350 case L'7': return 7;
351 case L'8': return 8;
352 case L'9': return 9;
353 case L'A':
354 case L'a':
355 return 10;
356 case L'B':
357 case L'b':
358 return 11;
359 case L'C':
360 case L'c':
361 return 12;
362 case L'D':
363 case L'd':
364 return 13;
365 case L'E':
366 case L'e':
367 return 14;
368 case L'F':
369 case L'f':
370 return 15;
371 }
372 return 0xFF;
373 }
374
375 BOOLEAN
376 IsValidNumericString(PNDIS_STRING String, ULONG Base)
377 /*
378 * FUNCTION: Determines if a string is a valid number
379 * ARGUMENTS:
380 * String: Unicode string to evaluate
381 * RETURNS:
382 * TRUE if it is valid, FALSE if not
383 */
384 {
385 ULONG i;
386
387 /* I don't think this will ever happen, but we warn it if it does */
388 if (String->Length == 0)
389 {
390 NDIS_DbgPrint(MIN_TRACE, ("Got an empty string; not sure what to do here\n"));
391 return FALSE;
392 }
393
394 for (i = 0; i < String->Length / sizeof(WCHAR); i++)
395 {
396 /* Skip any NULL characters we find */
397 if (String->Buffer[i] == UNICODE_NULL)
398 continue;
399
400 /* Make sure the character is valid for a numeric string of this base */
401 if (UnicodeToHexByte(String->Buffer[i]) >= Base)
402 return FALSE;
403 }
404
405 /* It's valid */
406 return TRUE;
407 }
408
409 /*
410 * @implemented
411 */
412 VOID
413 EXPORT
414 NdisReadConfiguration(
415 OUT PNDIS_STATUS Status,
416 OUT PNDIS_CONFIGURATION_PARAMETER * ParameterValue,
417 IN NDIS_HANDLE ConfigurationHandle,
418 IN PNDIS_STRING Keyword,
419 IN NDIS_PARAMETER_TYPE ParameterType)
420 /*
421 * FUNCTION: Read a configuration value from the registry, tracking its resources
422 * ARGUMENTS:
423 * Status: points to a place to write status into
424 * ParameterValue: Pointer to receive a newly-allocated parameter structure
425 * ConfigurationHandle: handle originally returned by an open function
426 * Keyword: Value name to read, or one of the following constants:
427 * Environment - returns NdisEnvironmentWindowsNt
428 * ProcessorType - returns NdisProcessorX86 until more architectures are added
429 * NdisVersion - returns NDIS_VERSION
430 * ParameterType: the type of the value to be queried
431 * RETURNS:
432 * - A status in Status
433 * - A parameter value in ParameterValue
434 */
435 {
436 KEY_VALUE_PARTIAL_INFORMATION *KeyInformation;
437 ULONG KeyDataLength;
438 PMINIPORT_RESOURCE MiniportResource;
439 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext = (PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle;
440 PVOID Buffer;
441
442 //*ParameterValue = NULL;
443 *Status = NDIS_STATUS_FAILURE;
444
445 NDIS_DbgPrint(MAX_TRACE,("requested read of %wZ\n", Keyword));
446 NDIS_DbgPrint(MID_TRACE,("requested parameter type: %d\n", ParameterType));
447
448 if (ConfigurationContext == NULL)
449 {
450 NDIS_DbgPrint(MIN_TRACE,("invalid parameter ConfigurationContext (0x%x)\n",ConfigurationContext));
451 return;
452 }
453
454 if(!wcsncmp(Keyword->Buffer, L"Environment", Keyword->Length/sizeof(WCHAR)) &&
455 wcslen(L"Environment") == Keyword->Length/sizeof(WCHAR))
456 {
457 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
458 if(!*ParameterValue)
459 {
460 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
461 *Status = NDIS_STATUS_RESOURCES;
462 return;
463 }
464
465 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
466 if(!MiniportResource)
467 {
468 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
469 ExFreePool(*ParameterValue);
470 *ParameterValue = NULL;
471 *Status = NDIS_STATUS_RESOURCES;
472 return;
473 }
474
475 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
476 MiniportResource->Resource = *ParameterValue;
477
478 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n",
479 MiniportResource->Resource));
480
481 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
482 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
483
484 (*ParameterValue)->ParameterType = NdisParameterInteger;
485 (*ParameterValue)->ParameterData.IntegerData = NdisEnvironmentWindowsNt;
486 *Status = NDIS_STATUS_SUCCESS;
487
488 return;
489 }
490
491 if(!wcsncmp(Keyword->Buffer, L"ProcessorType", Keyword->Length/sizeof(WCHAR)) &&
492 wcslen(L"ProcessorType") == Keyword->Length/sizeof(WCHAR))
493 {
494 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
495 if(!*ParameterValue)
496 {
497 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
498 *Status = NDIS_STATUS_RESOURCES;
499 return;
500 }
501
502 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
503 if(!MiniportResource)
504 {
505 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
506 ExFreePool(*ParameterValue);
507 *ParameterValue = NULL;
508 *Status = NDIS_STATUS_RESOURCES;
509 return;
510 }
511
512 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
513 MiniportResource->Resource = *ParameterValue;
514 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
515 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
516 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
517
518 (*ParameterValue)->ParameterType = NdisParameterInteger;
519 (*ParameterValue)->ParameterData.IntegerData = NdisProcessorX86; /* XXX non-portable */
520 *Status = NDIS_STATUS_SUCCESS;
521
522 return;
523 }
524
525 if(!wcsncmp(Keyword->Buffer, L"NdisVersion", Keyword->Length/sizeof(WCHAR)) &&
526 wcslen(L"NdisVersion") == Keyword->Length/sizeof(WCHAR))
527 {
528 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
529 if(!*ParameterValue)
530 {
531 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
532 *Status = NDIS_STATUS_RESOURCES;
533 return;
534 }
535
536 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
537 if(!MiniportResource)
538 {
539 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
540 ExFreePool(*ParameterValue);
541 *ParameterValue = NULL;
542 *Status = NDIS_STATUS_RESOURCES;
543 return;
544 }
545
546 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
547 MiniportResource->Resource = *ParameterValue;
548 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
549 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
550 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
551
552 (*ParameterValue)->ParameterType = NdisParameterInteger;
553 (*ParameterValue)->ParameterData.IntegerData = NDIS_VERSION;
554 *Status = NDIS_STATUS_SUCCESS;
555
556 NDIS_DbgPrint(MAX_TRACE,("ParameterType = %0x%x, ParameterValue = 0x%x\n",
557 (*ParameterValue)->ParameterType, (*ParameterValue)->ParameterData.IntegerData));
558 return;
559 }
560
561 /* figure out how much buffer i should allocate */
562 *Status = ZwQueryValueKey(ConfigurationContext->Handle, Keyword, KeyValuePartialInformation, NULL, 0, &KeyDataLength);
563 if(*Status != STATUS_BUFFER_OVERFLOW && *Status != STATUS_BUFFER_TOO_SMALL && *Status != STATUS_SUCCESS)
564 {
565 NDIS_DbgPrint(MID_TRACE,("ZwQueryValueKey #1 failed for %wZ, status 0x%x\n", Keyword, *Status));
566 *Status = NDIS_STATUS_FAILURE;
567 return;
568 }
569
570 /* allocate it */
571 KeyInformation = ExAllocatePool(PagedPool, KeyDataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION));
572 if(!KeyInformation)
573 {
574 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
575 *Status = NDIS_STATUS_RESOURCES;
576 return;
577 }
578
579 /* grab the value */
580 *Status = ZwQueryValueKey(ConfigurationContext->Handle, Keyword, KeyValuePartialInformation,
581 KeyInformation, KeyDataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION), &KeyDataLength);
582 if(*Status != STATUS_SUCCESS)
583 {
584 ExFreePool(KeyInformation);
585 NDIS_DbgPrint(MIN_TRACE,("ZwQueryValueKey #2 failed for %wZ, status 0x%x\n", Keyword, *Status));
586 *Status = NDIS_STATUS_FAILURE;
587 return;
588 }
589
590 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
591 if(!MiniportResource)
592 {
593 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
594 ExFreePool(KeyInformation);
595 *Status = NDIS_STATUS_RESOURCES;
596 return;
597 }
598
599 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
600 if (!*ParameterValue)
601 {
602 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
603 ExFreePool(MiniportResource);
604 ExFreePool(KeyInformation);
605 *Status = NDIS_STATUS_RESOURCES;
606 return;
607 }
608
609 RtlZeroMemory(*ParameterValue, sizeof(NDIS_CONFIGURATION_PARAMETER));
610
611 if (KeyInformation->Type == REG_BINARY)
612 {
613 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterBinary\n"));
614
615 (*ParameterValue)->ParameterType = NdisParameterBinary;
616
617 Buffer = ExAllocatePool(PagedPool, KeyInformation->DataLength);
618 if (!Buffer)
619 {
620 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
621 ExFreePool(MiniportResource);
622 ExFreePool(KeyInformation);
623 *Status = NDIS_STATUS_RESOURCES;
624 return;
625 }
626
627 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
628
629 (*ParameterValue)->ParameterData.BinaryData.Buffer = Buffer;
630 (*ParameterValue)->ParameterData.BinaryData.Length = KeyInformation->DataLength;
631 }
632 else if (KeyInformation->Type == REG_MULTI_SZ)
633 {
634 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterMultiString\n"));
635
636 (*ParameterValue)->ParameterType = NdisParameterMultiString;
637
638 Buffer = ExAllocatePool(PagedPool, KeyInformation->DataLength);
639 if (!Buffer)
640 {
641 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
642 ExFreePool(MiniportResource);
643 ExFreePool(KeyInformation);
644 *Status = NDIS_STATUS_RESOURCES;
645 return;
646 }
647
648 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
649
650 (*ParameterValue)->ParameterData.StringData.Buffer = Buffer;
651 (*ParameterValue)->ParameterData.StringData.Length = KeyInformation->DataLength;
652 }
653 else if (KeyInformation->Type == REG_DWORD)
654 {
655 ASSERT(KeyInformation->DataLength == sizeof(ULONG));
656 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterInteger\n"));
657 (*ParameterValue)->ParameterType = NdisParameterInteger;
658 (*ParameterValue)->ParameterData.IntegerData = * (ULONG *) &KeyInformation->Data[0];
659 }
660 else if (KeyInformation->Type == REG_SZ)
661 {
662 UNICODE_STRING str;
663 ULONG Base;
664
665 if (ParameterType == NdisParameterInteger)
666 Base = 10;
667 else if (ParameterType == NdisParameterHexInteger)
668 Base = 16;
669 else
670 Base = 0;
671
672 str.Length = str.MaximumLength = (USHORT)KeyInformation->DataLength;
673 str.Buffer = (PWCHAR)KeyInformation->Data;
674
675 if (Base != 0 && IsValidNumericString(&str, Base))
676 {
677 *Status = RtlUnicodeStringToInteger(&str, Base, &(*ParameterValue)->ParameterData.IntegerData);
678 ASSERT(*Status == STATUS_SUCCESS);
679
680 NDIS_DbgPrint(MAX_TRACE, ("NdisParameter(Hex)Integer\n"));
681
682 /* MSDN documents that this is returned for all integers, regardless of the ParameterType passed in */
683 (*ParameterValue)->ParameterType = NdisParameterInteger;
684 }
685 else
686 {
687 NDIS_DbgPrint(MAX_TRACE, ("NdisParameterString\n"));
688
689 (*ParameterValue)->ParameterType = NdisParameterString;
690
691 Buffer = ExAllocatePool(PagedPool, KeyInformation->DataLength);
692 if (!Buffer)
693 {
694 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
695 ExFreePool(MiniportResource);
696 ExFreePool(KeyInformation);
697 *Status = NDIS_STATUS_RESOURCES;
698 return;
699 }
700
701 RtlCopyMemory(Buffer, KeyInformation->Data, KeyInformation->DataLength);
702
703 (*ParameterValue)->ParameterData.StringData.Buffer = Buffer;
704 (*ParameterValue)->ParameterData.StringData.Length = KeyInformation->DataLength;
705 }
706 }
707 else
708 {
709 NDIS_DbgPrint(MIN_TRACE, ("Invalid type for NdisReadConfiguration (%d)\n", KeyInformation->Type));
710 NDIS_DbgPrint(MIN_TRACE, ("Requested type: %d\n", ParameterType));
711 NDIS_DbgPrint(MIN_TRACE, ("Registry entry: %wZ\n", Keyword));
712 *Status = NDIS_STATUS_FAILURE;
713 ExFreePool(KeyInformation);
714 return;
715 }
716
717 if (((*ParameterValue)->ParameterType != ParameterType) &&
718 !((ParameterType == NdisParameterHexInteger) && ((*ParameterValue)->ParameterType == NdisParameterInteger)))
719 {
720 NDIS_DbgPrint(MIN_TRACE, ("Parameter type mismatch! (Requested: %d | Received: %d)\n",
721 ParameterType, (*ParameterValue)->ParameterType));
722 NDIS_DbgPrint(MIN_TRACE, ("Registry entry: %wZ\n", Keyword));
723 }
724
725 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_REGISTRY_DATA;
726 MiniportResource->Resource = *ParameterValue;
727
728 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
729
730 ExFreePool(KeyInformation);
731
732 *Status = NDIS_STATUS_SUCCESS;
733 }
734
735 /*
736 * @implemented
737 */
738 VOID
739 EXPORT
740 NdisReadNetworkAddress(
741 OUT PNDIS_STATUS Status,
742 OUT PVOID * NetworkAddress,
743 OUT PUINT NetworkAddressLength,
744 IN NDIS_HANDLE ConfigurationHandle)
745 /*
746 * FUNCTION: Reads the network address from the registry
747 * ARGUMENTS:
748 * Status - variable to receive status
749 * NetworkAddress - pointer to a buffered network address array
750 * NetworkAddressLength - length of the NetworkAddress array
751 * ConfigurationHandle: handle passed back from one of the open routines
752 * RETURNS:
753 * NDIS_STATUS_SUCCESS on success
754 * NDIS_STATUS_FAILURE on failure
755 * The network address is placed in the NetworkAddress buffer
756 */
757 {
758 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext = (PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle;
759 PMINIPORT_RESOURCE MiniportResource = NULL;
760 PNDIS_CONFIGURATION_PARAMETER ParameterValue = NULL;
761 NDIS_STRING Keyword;
762 UINT *IntArray = 0;
763 UINT i,j = 0;
764 NDIS_STRING str;
765
766 NdisInitUnicodeString(&Keyword, L"NetworkAddress");
767 NdisReadConfiguration(Status, &ParameterValue, ConfigurationHandle, &Keyword, NdisParameterString);
768 if(*Status != NDIS_STATUS_SUCCESS)
769 {
770 NDIS_DbgPrint(MID_TRACE, ("NdisReadConfiguration failed (%x)\n", *Status));
771 *Status = NDIS_STATUS_FAILURE;
772 return;
773 }
774
775 if (ParameterValue->ParameterType == NdisParameterInteger)
776 {
777 WCHAR Buff[11];
778
779 NDIS_DbgPrint(MAX_TRACE, ("Read integer data %lx\n",
780 ParameterValue->ParameterData.IntegerData));
781
782 str.Buffer = Buff;
783 str.MaximumLength = (USHORT)sizeof(Buff);
784 str.Length = 0;
785
786 *Status = RtlIntegerToUnicodeString(ParameterValue->ParameterData.IntegerData,
787 10,
788 &str);
789
790 if (*Status != NDIS_STATUS_SUCCESS)
791 {
792 NDIS_DbgPrint(MIN_TRACE, ("RtlIntegerToUnicodeString failed (%x)\n", *Status));
793 *Status = NDIS_STATUS_FAILURE;
794 return;
795 }
796
797 NDIS_DbgPrint(MAX_TRACE, ("Converted integer data into %wZ\n", &str));
798 }
799 else
800 {
801 ASSERT(ParameterValue->ParameterType == NdisParameterString);
802 str = ParameterValue->ParameterData.StringData;
803 }
804
805 while (j < str.Length && str.Buffer[j] != '\0') j++;
806
807 *NetworkAddressLength = (j+1) >> 1;
808
809 if ((*NetworkAddressLength) == 0)
810 {
811 NDIS_DbgPrint(MIN_TRACE,("Empty NetworkAddress registry entry.\n"));
812 *Status = NDIS_STATUS_FAILURE;
813 return;
814 }
815
816 IntArray = ExAllocatePool(PagedPool, (*NetworkAddressLength)*sizeof(UINT));
817 if(!IntArray)
818 {
819 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
820 *Status = NDIS_STATUS_RESOURCES;
821 return;
822 }
823
824 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
825 if(!MiniportResource)
826 {
827 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
828 ExFreePool(IntArray);
829 *Status = NDIS_STATUS_RESOURCES;
830 return;
831 }
832
833 MiniportResource->ResourceType = MINIPORT_RESOURCE_TYPE_MEMORY;
834 MiniportResource->Resource = IntArray;
835 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
836 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
837
838 /* convert from string to bytes */
839 for(i=0; i<(*NetworkAddressLength); i++)
840 {
841 IntArray[i] = (UnicodeToHexByte((str.Buffer)[2*i]) << 4) +
842 UnicodeToHexByte((str.Buffer)[2*i+1]);
843 }
844
845 *NetworkAddress = IntArray;
846
847 *Status = NDIS_STATUS_SUCCESS;
848 }
849
850
851 /*
852 * @implemented
853 */
854 VOID
855 EXPORT
856 NdisOpenConfigurationKeyByIndex(
857 OUT PNDIS_STATUS Status,
858 IN NDIS_HANDLE ConfigurationHandle,
859 IN ULONG Index,
860 OUT PNDIS_STRING KeyName,
861 OUT PNDIS_HANDLE KeyHandle)
862 /*
863 * FUNCTION: Opens a configuration subkey by index number
864 * ARGUMENTS:
865 * Status: pointer to an NDIS_STATUS to receive status info
866 * ConfigurationHandle: the handle passed back from a previous open function
867 * Index: the zero-based index of the subkey to open
868 * KeyName: the name of the key that was opened
869 * KeyHandle: a handle to the key that was opened
870 * RETURNS:
871 * NDIS_STATUS_SUCCESS on success
872 * NDIS_STATUS_FAILURE on failure
873 * KeyName holds the name of the opened key
874 * KeyHandle holds a handle to the new key
875 */
876 {
877 KEY_BASIC_INFORMATION *KeyInformation;
878 ULONG KeyInformationLength;
879 OBJECT_ATTRIBUTES KeyAttributes;
880 NDIS_HANDLE RegKeyHandle;
881 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
882
883 *KeyHandle = NULL;
884
885 *Status = ZwEnumerateKey(ConfigurationHandle, Index, KeyBasicInformation, NULL, 0, &KeyInformationLength);
886 if(*Status != STATUS_BUFFER_TOO_SMALL && *Status != STATUS_BUFFER_OVERFLOW && *Status != STATUS_SUCCESS)
887 {
888 NDIS_DbgPrint(MIN_TRACE, ("ZwEnumerateKey failed (%x)\n", *Status));
889 *Status = NDIS_STATUS_FAILURE;
890 return;
891 }
892
893 KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength + sizeof(KEY_BASIC_INFORMATION));
894 if(!KeyInformation)
895 {
896 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
897 *Status = NDIS_STATUS_FAILURE;
898 return;
899 }
900
901 *Status = ZwEnumerateKey(ConfigurationHandle, Index, KeyBasicInformation, KeyInformation,
902 KeyInformationLength + sizeof(KEY_BASIC_INFORMATION), &KeyInformationLength);
903
904 if(*Status != STATUS_SUCCESS)
905 {
906 NDIS_DbgPrint(MIN_TRACE, ("ZwEnumerateKey failed (%x)\n", *Status));
907 ExFreePool(KeyInformation);
908 *Status = NDIS_STATUS_FAILURE;
909 return;
910 }
911
912 /* should i fail instead if the passed-in string isn't long enough? */
913 wcsncpy(KeyName->Buffer, KeyInformation->Name, KeyName->MaximumLength/sizeof(WCHAR));
914 KeyName->Length = (USHORT)min(KeyInformation->NameLength, KeyName->MaximumLength);
915
916 InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, ConfigurationHandle, NULL);
917
918 *Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
919
920 ExFreePool(KeyInformation);
921
922 if(*Status != STATUS_SUCCESS)
923 {
924 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
925 *Status = NDIS_STATUS_FAILURE;
926 return;
927 }
928
929 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
930 if(!ConfigurationContext)
931 {
932 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
933 ZwClose(RegKeyHandle);
934 *Status = NDIS_STATUS_FAILURE;
935 return;
936 }
937
938 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
939 InitializeListHead(&ConfigurationContext->ResourceListHead);
940
941 ConfigurationContext->Handle = RegKeyHandle;
942
943 *KeyHandle = (NDIS_HANDLE)ConfigurationContext;
944
945 *Status = NDIS_STATUS_SUCCESS;
946 }
947
948
949 /*
950 * @implemented
951 */
952 VOID
953 EXPORT
954 NdisOpenConfigurationKeyByName(
955 OUT PNDIS_STATUS Status,
956 IN NDIS_HANDLE ConfigurationHandle,
957 IN PNDIS_STRING KeyName,
958 OUT PNDIS_HANDLE KeyHandle)
959 /*
960 * FUNCTION: Opens a configuration subkey by name
961 * ARGUMENTS:
962 * Status: points to an NDIS_STATUS where status is returned
963 * ConfigurationHandle: handle returned by a previous open call
964 * KeyName: the name of the key to open
965 * KeyHandle: a handle to the opened key
966 * RETURNS:
967 * NDIS_STATUS_SUCCESS on success
968 * NDIS_STATUS_FAILURE on failure
969 * KeyHandle holds a handle to the newly-opened key
970 * NOTES:
971 */
972 {
973 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
974 OBJECT_ATTRIBUTES KeyAttributes;
975 NDIS_HANDLE RegKeyHandle;
976
977 *KeyHandle = NULL;
978
979 InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, ConfigurationHandle, 0);
980 *Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
981
982 if(*Status != STATUS_SUCCESS)
983 {
984 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
985 *Status = NDIS_STATUS_FAILURE;
986 return;
987 }
988
989 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
990 if(!ConfigurationContext)
991 {
992 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
993 ZwClose(RegKeyHandle);
994 *Status = NDIS_STATUS_FAILURE;
995 return;
996 }
997
998 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
999 InitializeListHead(&ConfigurationContext->ResourceListHead);
1000
1001 ConfigurationContext->Handle = RegKeyHandle;
1002
1003 *KeyHandle = (NDIS_HANDLE)ConfigurationContext;
1004
1005 *Status = NDIS_STATUS_SUCCESS;
1006 }