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