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