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