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