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