2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
5 * PURPOSE: NDIS Configuration Services
6 * PROGRAMMERS: Vizzini (vizzini@plasmic.com)
8 * Vizzini 07-28-2003 Created
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
31 * - All the routines in this file are PASSIVE_LEVEL only, and all memory is PagedPool
36 #define PARAMETERS_KEY L"Parameters" /* The parameters subkey under the device-specific key */
43 NdisWriteConfiguration(
44 OUT PNDIS_STATUS Status
,
45 IN NDIS_HANDLE ConfigurationHandle
,
46 IN PNDIS_STRING Keyword
,
47 IN PNDIS_CONFIGURATION_PARAMETER ParameterValue
)
49 * FUNCTION: Writes a configuration value to the registry
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
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
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.
70 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
72 NDIS_DbgPrint(MID_TRACE
, ("Parameter type: %d\n", ParameterValue
->ParameterType
));
74 /* reset parameter type to standard reg types */
75 switch(ParameterValue
->ParameterType
)
77 case NdisParameterHexInteger
:
78 case NdisParameterInteger
:
82 Str
.Buffer
= (PWSTR
) &Buff
;
83 Str
.MaximumLength
= (USHORT
)sizeof(Buff
);
86 ParameterType
= REG_SZ
;
87 if (!NT_SUCCESS(RtlIntegerToUnicodeString(
88 ParameterValue
->ParameterData
.IntegerData
,
89 (ParameterValue
->ParameterType
== NdisParameterInteger
) ? 10 : 16, &Str
)))
91 NDIS_DbgPrint(MIN_TRACE
, ("RtlIntegerToUnicodeString failed (%x)\n", *Status
));
92 *Status
= NDIS_STATUS_FAILURE
;
96 DataSize
= Str
.Length
;
99 case NdisParameterString
:
100 case NdisParameterMultiString
:
101 ParameterType
= (ParameterValue
->ParameterType
== NdisParameterString
) ? REG_SZ
: REG_MULTI_SZ
;
102 Data
= ParameterValue
->ParameterData
.StringData
.Buffer
;
103 DataSize
= ParameterValue
->ParameterData
.StringData
.Length
;
106 /* New (undocumented) addition to 2k ddk */
107 case NdisParameterBinary
:
108 ParameterType
= REG_BINARY
;
109 Data
= ParameterValue
->ParameterData
.BinaryData
.Buffer
;
110 DataSize
= ParameterValue
->ParameterData
.BinaryData
.Length
;
114 *Status
= NDIS_STATUS_NOT_SUPPORTED
;
118 *Status
= ZwSetValueKey(((PMINIPORT_CONFIGURATION_CONTEXT
)ConfigurationHandle
)->Handle
,
119 Keyword
, 0, ParameterType
, Data
, DataSize
);
121 if(*Status
!= STATUS_SUCCESS
) {
122 NDIS_DbgPrint(MIN_TRACE
, ("ZwSetValueKey failed (%x)\n", *Status
));
123 *Status
= NDIS_STATUS_FAILURE
;
125 *Status
= NDIS_STATUS_SUCCESS
;
134 NdisCloseConfiguration(
135 IN NDIS_HANDLE ConfigurationHandle
)
137 * FUNCTION: Closes handles and releases per-handle resources
139 * ConfigurationHandle - pointer to the context with the resources to free
142 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
= (PMINIPORT_CONFIGURATION_CONTEXT
)ConfigurationHandle
;
143 PMINIPORT_RESOURCE Resource
;
144 PNDIS_CONFIGURATION_PARAMETER ParameterValue
;
145 PLIST_ENTRY CurrentEntry
;
147 while((CurrentEntry
= ExInterlockedRemoveHeadList(&ConfigurationContext
->ResourceListHead
,
148 &ConfigurationContext
->ResourceLock
)) != NULL
)
150 Resource
= CONTAINING_RECORD(CurrentEntry
, MINIPORT_RESOURCE
, ListEntry
);
151 switch(Resource
->ResourceType
)
153 case MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
:
154 ParameterValue
= Resource
->Resource
;
156 switch (ParameterValue
->ParameterType
)
158 case NdisParameterBinary
:
159 ExFreePool(ParameterValue
->ParameterData
.BinaryData
.Buffer
);
162 case NdisParameterString
:
163 case NdisParameterMultiString
:
164 ExFreePool(ParameterValue
->ParameterData
.StringData
.Buffer
);
171 /* Fall through to free NDIS_CONFIGURATION_PARAMETER struct */
173 case MINIPORT_RESOURCE_TYPE_MEMORY
:
174 NDIS_DbgPrint(MAX_TRACE
,("freeing 0x%x\n", Resource
->Resource
));
175 ExFreePool(Resource
->Resource
);
179 NDIS_DbgPrint(MIN_TRACE
,("Unknown resource type: %d\n", Resource
->ResourceType
));
183 ExFreePool(Resource
);
186 ZwClose(ConfigurationContext
->Handle
);
195 NdisOpenConfiguration(
196 OUT PNDIS_STATUS Status
,
197 OUT PNDIS_HANDLE ConfigurationHandle
,
198 IN NDIS_HANDLE WrapperConfigurationContext
)
200 * FUNCTION: Opens the configuration key and sets up resource tracking for the returned handle
202 * Status: Pointer to a caller-supplied NDIS_STATUS that is filled in with a return value
203 * ConfigurationHandle: Pointer to an opaque configuration handle returned on success
204 * WrapperConfigurationContext: handle originally passed back from NdisInitializeWrapper
206 * NDIS_STATUS_SUCCESS: the operation completed successfully
207 * NDIS_STATUS_FAILURE: the operation failed
209 * I think this is the parameters key; please verify.
213 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
;
214 PNDIS_WRAPPER_CONTEXT WrapperContext
= (PNDIS_WRAPPER_CONTEXT
)WrapperConfigurationContext
;
215 HANDLE RootKeyHandle
= WrapperContext
->RegistryHandle
;
217 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
219 *ConfigurationHandle
= NULL
;
221 *Status
= ZwDuplicateObject(NtCurrentProcess(), RootKeyHandle
,
222 NtCurrentProcess(), &KeyHandle
, 0, 0,
223 DUPLICATE_SAME_ACCESS
);
224 if(!NT_SUCCESS(*Status
))
226 NDIS_DbgPrint(MIN_TRACE
, ("Failed to open registry configuration for this miniport\n"));
227 *Status
= NDIS_STATUS_FAILURE
;
231 ConfigurationContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_CONFIGURATION_CONTEXT
));
232 if(!ConfigurationContext
)
234 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
236 *Status
= NDIS_STATUS_RESOURCES
;
240 KeInitializeSpinLock(&ConfigurationContext
->ResourceLock
);
241 InitializeListHead(&ConfigurationContext
->ResourceListHead
);
243 ConfigurationContext
->Handle
= KeyHandle
;
245 *ConfigurationHandle
= (NDIS_HANDLE
)ConfigurationContext
;
246 *Status
= NDIS_STATUS_SUCCESS
;
248 NDIS_DbgPrint(MAX_TRACE
,("returning success\n"));
257 NdisOpenProtocolConfiguration(
258 OUT PNDIS_STATUS Status
,
259 OUT PNDIS_HANDLE ConfigurationHandle
,
260 IN PNDIS_STRING ProtocolSection
)
262 * FUNCTION: Open the configuration key and set up resource tracking for the protocol
264 * Status: caller-allocated buffer where status is returned
265 * ConfigurationHandle: spot to return the opaque configuration context
266 * ProtocolSection: configuration string originally passed in to ProtocolBindAdapter
268 * NDIS_STATUS_SUCCESS: the operation was a success
269 * NDIS_STATUS_FAILURE: the operation was not a success
271 * I think this is the per-device (adapter) parameters\{ProtocolName} key; please verify.
274 OBJECT_ATTRIBUTES KeyAttributes
;
275 UNICODE_STRING KeyNameU
;
277 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
;
280 KeyNameU
.MaximumLength
= ProtocolSection
->Length
+ sizeof(PARAMETERS_KEY
) + sizeof(UNICODE_NULL
);
281 KeyNameU
.Buffer
= ExAllocatePool(PagedPool
, KeyNameU
.MaximumLength
);
284 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
285 *ConfigurationHandle
= NULL
;
286 *Status
= NDIS_STATUS_FAILURE
;
290 RtlCopyUnicodeString(&KeyNameU
, ProtocolSection
);
291 RtlAppendUnicodeToString(&KeyNameU
, PARAMETERS_KEY
);
292 InitializeObjectAttributes(&KeyAttributes
, &KeyNameU
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
294 *Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &KeyAttributes
);
296 ExFreePool(KeyNameU
.Buffer
);
298 if(*Status
!= NDIS_STATUS_SUCCESS
)
300 NDIS_DbgPrint(MIN_TRACE
, ("ZwOpenKey failed (%x)\n", *Status
));
301 *ConfigurationHandle
= NULL
;
302 *Status
= NDIS_STATUS_FAILURE
;
306 ConfigurationContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_CONFIGURATION_CONTEXT
));
307 if(!ConfigurationContext
)
309 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
311 *ConfigurationHandle
= NULL
;
312 *Status
= NDIS_STATUS_FAILURE
;
316 KeInitializeSpinLock(&ConfigurationContext
->ResourceLock
);
317 InitializeListHead(&ConfigurationContext
->ResourceListHead
);
319 ConfigurationContext
->Handle
= KeyHandle
;
321 *ConfigurationHandle
= (NDIS_HANDLE
)ConfigurationContext
;
322 *Status
= NDIS_STATUS_SUCCESS
;
325 UCHAR
UnicodeToHexByte(WCHAR chr
)
327 * FUNCTION: Converts a unicode hex character to its numerical value
329 * chr: Unicode character to convert
331 * The numerical value of chr
369 IsValidNumericString(PNDIS_STRING String
, ULONG Base
)
371 * FUNCTION: Determines if a string is a valid number
373 * String: Unicode string to evaluate
375 * TRUE if it is valid, FALSE if not
380 /* I don't think this will ever happen, but we warn it if it does */
381 if (String
->Length
== 0)
383 NDIS_DbgPrint(MIN_TRACE
, ("Got an empty string; not sure what to do here\n"));
387 for (i
= 0; i
< String
->Length
/ sizeof(WCHAR
); i
++)
389 /* Skip any NULL characters we find */
390 if (String
->Buffer
[i
] == UNICODE_NULL
)
393 /* Make sure the character is valid for a numeric string of this base */
394 if (UnicodeToHexByte(String
->Buffer
[i
]) >= Base
)
407 NdisReadConfiguration(
408 OUT PNDIS_STATUS Status
,
409 OUT PNDIS_CONFIGURATION_PARAMETER
* ParameterValue
,
410 IN NDIS_HANDLE ConfigurationHandle
,
411 IN PNDIS_STRING Keyword
,
412 IN NDIS_PARAMETER_TYPE ParameterType
)
414 * FUNCTION: Read a configuration value from the registry, tracking its resources
416 * Status: points to a place to write status into
417 * ParameterValue: Pointer to receive a newly-allocated parameter structure
418 * ConfigurationHandle: handle originally returned by an open function
419 * Keyword: Value name to read, or one of the following constants:
420 * Environment - returns NdisEnvironmentWindowsNt
421 * ProcessorType - returns NdisProcessorX86 until more architectures are added
422 * NdisVersion - returns NDIS_VERSION
423 * ParameterType: the type of the value to be queried
425 * - A status in Status
426 * - A parameter value in ParameterValue
429 KEY_VALUE_PARTIAL_INFORMATION
*KeyInformation
;
431 PMINIPORT_RESOURCE MiniportResource
;
432 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
= (PMINIPORT_CONFIGURATION_CONTEXT
)ConfigurationHandle
;
435 *ParameterValue
= NULL
;
436 *Status
= NDIS_STATUS_FAILURE
;
438 NDIS_DbgPrint(MAX_TRACE
,("requested read of %wZ\n", Keyword
));
439 NDIS_DbgPrint(MID_TRACE
,("requested parameter type: %d\n", ParameterType
));
441 if (ConfigurationContext
== NULL
)
443 NDIS_DbgPrint(MIN_TRACE
,("invalid parameter ConfigurationContext (0x%x)\n",ConfigurationContext
));
447 if(!wcsncmp(Keyword
->Buffer
, L
"Environment", Keyword
->Length
/sizeof(WCHAR
)) &&
448 wcslen(L
"Environment") == Keyword
->Length
/sizeof(WCHAR
))
450 *ParameterValue
= ExAllocatePool(PagedPool
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
453 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
454 *Status
= NDIS_STATUS_RESOURCES
;
458 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
459 if(!MiniportResource
)
461 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
462 ExFreePool(*ParameterValue
);
463 *ParameterValue
= NULL
;
464 *Status
= NDIS_STATUS_RESOURCES
;
468 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
;
469 MiniportResource
->Resource
= *ParameterValue
;
471 NDIS_DbgPrint(MID_TRACE
,("inserting 0x%x into the resource list\n",
472 MiniportResource
->Resource
));
474 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
,
475 &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
477 (*ParameterValue
)->ParameterType
= NdisParameterInteger
;
478 (*ParameterValue
)->ParameterData
.IntegerData
= NdisEnvironmentWindowsNt
;
479 *Status
= NDIS_STATUS_SUCCESS
;
484 if(!wcsncmp(Keyword
->Buffer
, L
"ProcessorType", Keyword
->Length
/sizeof(WCHAR
)) &&
485 wcslen(L
"ProcessorType") == Keyword
->Length
/sizeof(WCHAR
))
487 *ParameterValue
= ExAllocatePool(PagedPool
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
490 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
491 *Status
= NDIS_STATUS_RESOURCES
;
495 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
496 if(!MiniportResource
)
498 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
499 ExFreePool(*ParameterValue
);
500 *ParameterValue
= NULL
;
501 *Status
= NDIS_STATUS_RESOURCES
;
505 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
;
506 MiniportResource
->Resource
= *ParameterValue
;
507 NDIS_DbgPrint(MID_TRACE
,("inserting 0x%x into the resource list\n", MiniportResource
->Resource
));
508 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
,
509 &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
511 (*ParameterValue
)->ParameterType
= NdisParameterInteger
;
512 (*ParameterValue
)->ParameterData
.IntegerData
= NdisProcessorX86
; /* XXX non-portable */
513 *Status
= NDIS_STATUS_SUCCESS
;
518 if(!wcsncmp(Keyword
->Buffer
, L
"NdisVersion", Keyword
->Length
/sizeof(WCHAR
)) &&
519 wcslen(L
"NdisVersion") == Keyword
->Length
/sizeof(WCHAR
))
521 *ParameterValue
= ExAllocatePool(PagedPool
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
524 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
525 *Status
= NDIS_STATUS_RESOURCES
;
529 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
530 if(!MiniportResource
)
532 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
533 ExFreePool(*ParameterValue
);
534 *ParameterValue
= NULL
;
535 *Status
= NDIS_STATUS_RESOURCES
;
539 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
;
540 MiniportResource
->Resource
= *ParameterValue
;
541 NDIS_DbgPrint(MID_TRACE
,("inserting 0x%x into the resource list\n", MiniportResource
->Resource
));
542 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
,
543 &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
545 (*ParameterValue
)->ParameterType
= NdisParameterInteger
;
546 (*ParameterValue
)->ParameterData
.IntegerData
= NDIS_VERSION
;
547 *Status
= NDIS_STATUS_SUCCESS
;
549 NDIS_DbgPrint(MAX_TRACE
,("ParameterType = %0x%x, ParameterValue = 0x%x\n",
550 (*ParameterValue
)->ParameterType
, (*ParameterValue
)->ParameterData
.IntegerData
));
554 /* figure out how much buffer i should allocate */
555 *Status
= ZwQueryValueKey(ConfigurationContext
->Handle
, Keyword
, KeyValuePartialInformation
, NULL
, 0, &KeyDataLength
);
556 if(*Status
!= STATUS_BUFFER_OVERFLOW
&& *Status
!= STATUS_BUFFER_TOO_SMALL
&& *Status
!= STATUS_SUCCESS
)
558 NDIS_DbgPrint(MID_TRACE
,("ZwQueryValueKey #1 failed for %wZ, status 0x%x\n", Keyword
, *Status
));
559 *Status
= NDIS_STATUS_FAILURE
;
564 KeyInformation
= ExAllocatePool(PagedPool
, KeyDataLength
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION
));
567 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
568 *Status
= NDIS_STATUS_RESOURCES
;
573 *Status
= ZwQueryValueKey(ConfigurationContext
->Handle
, Keyword
, KeyValuePartialInformation
,
574 KeyInformation
, KeyDataLength
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION
), &KeyDataLength
);
575 if(*Status
!= STATUS_SUCCESS
)
577 ExFreePool(KeyInformation
);
578 NDIS_DbgPrint(MIN_TRACE
,("ZwQueryValueKey #2 failed for %wZ, status 0x%x\n", Keyword
, *Status
));
579 *Status
= NDIS_STATUS_FAILURE
;
583 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
584 if(!MiniportResource
)
586 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
587 ExFreePool(KeyInformation
);
588 *Status
= NDIS_STATUS_RESOURCES
;
592 *ParameterValue
= ExAllocatePool(PagedPool
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
593 if (!*ParameterValue
)
595 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
596 ExFreePool(MiniportResource
);
597 ExFreePool(KeyInformation
);
598 *Status
= NDIS_STATUS_RESOURCES
;
602 RtlZeroMemory(*ParameterValue
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
604 if (KeyInformation
->Type
== REG_BINARY
)
606 NDIS_DbgPrint(MAX_TRACE
, ("NdisParameterBinary\n"));
608 (*ParameterValue
)->ParameterType
= NdisParameterBinary
;
610 Buffer
= ExAllocatePool(PagedPool
, KeyInformation
->DataLength
);
613 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
614 ExFreePool(MiniportResource
);
615 ExFreePool(KeyInformation
);
616 *Status
= NDIS_STATUS_RESOURCES
;
620 RtlCopyMemory(Buffer
, KeyInformation
->Data
, KeyInformation
->DataLength
);
622 (*ParameterValue
)->ParameterData
.BinaryData
.Buffer
= Buffer
;
623 (*ParameterValue
)->ParameterData
.BinaryData
.Length
= KeyInformation
->DataLength
;
625 else if (KeyInformation
->Type
== REG_MULTI_SZ
)
627 NDIS_DbgPrint(MAX_TRACE
, ("NdisParameterMultiString\n"));
629 (*ParameterValue
)->ParameterType
= NdisParameterMultiString
;
631 Buffer
= ExAllocatePool(PagedPool
, KeyInformation
->DataLength
);
634 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
635 ExFreePool(MiniportResource
);
636 ExFreePool(KeyInformation
);
637 *Status
= NDIS_STATUS_RESOURCES
;
641 RtlCopyMemory(Buffer
, KeyInformation
->Data
, KeyInformation
->DataLength
);
643 (*ParameterValue
)->ParameterData
.StringData
.Buffer
= Buffer
;
644 (*ParameterValue
)->ParameterData
.StringData
.Length
= KeyInformation
->DataLength
;
646 else if (KeyInformation
->Type
== REG_SZ
)
651 if (ParameterType
== NdisParameterInteger
)
653 else if (ParameterType
== NdisParameterHexInteger
)
658 str
.Length
= str
.MaximumLength
= (USHORT
)KeyInformation
->DataLength
;
659 str
.Buffer
= (PWCHAR
)KeyInformation
->Data
;
661 if (Base
!= 0 && IsValidNumericString(&str
, Base
))
663 *Status
= RtlUnicodeStringToInteger(&str
, Base
, &(*ParameterValue
)->ParameterData
.IntegerData
);
664 ASSERT(*Status
== STATUS_SUCCESS
);
666 NDIS_DbgPrint(MAX_TRACE
, ("NdisParameter(Hex)Integer\n"));
668 /* MSDN documents that this is returned for all integers, regardless of the ParameterType passed in */
669 (*ParameterValue
)->ParameterType
= NdisParameterInteger
;
673 NDIS_DbgPrint(MAX_TRACE
, ("NdisParameterString\n"));
675 (*ParameterValue
)->ParameterType
= NdisParameterString
;
677 Buffer
= ExAllocatePool(PagedPool
, KeyInformation
->DataLength
);
680 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
681 ExFreePool(MiniportResource
);
682 ExFreePool(KeyInformation
);
683 *Status
= NDIS_STATUS_RESOURCES
;
687 RtlCopyMemory(Buffer
, KeyInformation
->Data
, KeyInformation
->DataLength
);
689 (*ParameterValue
)->ParameterData
.StringData
.Buffer
= Buffer
;
690 (*ParameterValue
)->ParameterData
.StringData
.Length
= KeyInformation
->DataLength
;
695 NDIS_DbgPrint(MIN_TRACE
, ("Invalid type for NdisReadConfiguration (%d)\n", KeyInformation
->Type
));
696 NDIS_DbgPrint(MIN_TRACE
, ("Requested type: %d\n", ParameterType
));
697 NDIS_DbgPrint(MIN_TRACE
, ("Registry entry: %wZ\n", Keyword
));
698 *Status
= NDIS_STATUS_FAILURE
;
699 ExFreePool(KeyInformation
);
703 if (((*ParameterValue
)->ParameterType
!= ParameterType
) &&
704 !((ParameterType
== NdisParameterHexInteger
) && ((*ParameterValue
)->ParameterType
== NdisParameterInteger
)))
706 NDIS_DbgPrint(MIN_TRACE
, ("Parameter type mismatch! (Requested: %d | Received: %d)\n",
707 ParameterType
, (*ParameterValue
)->ParameterType
));
708 NDIS_DbgPrint(MIN_TRACE
, ("Registry entry: %wZ\n", Keyword
));
711 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
;
712 MiniportResource
->Resource
= *ParameterValue
;
714 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
, &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
716 ExFreePool(KeyInformation
);
718 *Status
= NDIS_STATUS_SUCCESS
;
726 NdisReadNetworkAddress(
727 OUT PNDIS_STATUS Status
,
728 OUT PVOID
* NetworkAddress
,
729 OUT PUINT NetworkAddressLength
,
730 IN NDIS_HANDLE ConfigurationHandle
)
732 * FUNCTION: Reads the network address from the registry
734 * Status - variable to receive status
735 * NetworkAddress - pointer to a buffered network address array
736 * NetworkAddressLength - length of the NetworkAddress array
737 * ConfigurationHandle: handle passed back from one of the open routines
739 * NDIS_STATUS_SUCCESS on success
740 * NDIS_STATUS_FAILURE on failure
741 * The network address is placed in the NetworkAddress buffer
744 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
= (PMINIPORT_CONFIGURATION_CONTEXT
)ConfigurationHandle
;
745 PMINIPORT_RESOURCE MiniportResource
= NULL
;
746 PNDIS_CONFIGURATION_PARAMETER ParameterValue
= NULL
;
752 NdisInitUnicodeString(&Keyword
, L
"NetworkAddress");
753 NdisReadConfiguration(Status
, &ParameterValue
, ConfigurationHandle
, &Keyword
, NdisParameterString
);
754 if(*Status
!= NDIS_STATUS_SUCCESS
)
756 NDIS_DbgPrint(MID_TRACE
, ("NdisReadConfiguration failed (%x)\n", *Status
));
757 *Status
= NDIS_STATUS_FAILURE
;
761 if (ParameterValue
->ParameterType
== NdisParameterInteger
)
765 NDIS_DbgPrint(MAX_TRACE
, ("Read integer data %lx\n",
766 ParameterValue
->ParameterData
.IntegerData
));
769 str
.MaximumLength
= (USHORT
)sizeof(Buff
);
772 *Status
= RtlIntegerToUnicodeString(ParameterValue
->ParameterData
.IntegerData
,
776 if (*Status
!= NDIS_STATUS_SUCCESS
)
778 NDIS_DbgPrint(MIN_TRACE
, ("RtlIntegerToUnicodeString failed (%x)\n", *Status
));
779 *Status
= NDIS_STATUS_FAILURE
;
783 NDIS_DbgPrint(MAX_TRACE
, ("Converted integer data into %wZ\n", &str
));
787 ASSERT(ParameterValue
->ParameterType
== NdisParameterString
);
788 str
= ParameterValue
->ParameterData
.StringData
;
791 while (j
< str
.Length
&& str
.Buffer
[j
] != '\0') j
++;
793 *NetworkAddressLength
= (j
+1) >> 1;
795 if ((*NetworkAddressLength
) == 0)
797 NDIS_DbgPrint(MIN_TRACE
,("Empty NetworkAddress registry entry.\n"));
798 *Status
= NDIS_STATUS_FAILURE
;
802 IntArray
= ExAllocatePool(PagedPool
, (*NetworkAddressLength
)*sizeof(UINT
));
805 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
806 *Status
= NDIS_STATUS_RESOURCES
;
810 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
811 if(!MiniportResource
)
813 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
814 ExFreePool(IntArray
);
815 *Status
= NDIS_STATUS_RESOURCES
;
819 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_MEMORY
;
820 MiniportResource
->Resource
= IntArray
;
821 NDIS_DbgPrint(MID_TRACE
,("inserting 0x%x into the resource list\n", MiniportResource
->Resource
));
822 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
, &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
824 /* convert from string to bytes */
825 for(i
=0; i
<(*NetworkAddressLength
); i
++)
827 IntArray
[i
] = (UnicodeToHexByte((str
.Buffer
)[2*i
]) << 4) +
828 UnicodeToHexByte((str
.Buffer
)[2*i
+1]);
831 *NetworkAddress
= IntArray
;
833 *Status
= NDIS_STATUS_SUCCESS
;
842 NdisOpenConfigurationKeyByIndex(
843 OUT PNDIS_STATUS Status
,
844 IN NDIS_HANDLE ConfigurationHandle
,
846 OUT PNDIS_STRING KeyName
,
847 OUT PNDIS_HANDLE KeyHandle
)
849 * FUNCTION: Opens a configuration subkey by index number
851 * Status: pointer to an NDIS_STATUS to receive status info
852 * ConfigurationHandle: the handle passed back from a previous open function
853 * Index: the zero-based index of the subkey to open
854 * KeyName: the name of the key that was opened
855 * KeyHandle: a handle to the key that was opened
857 * NDIS_STATUS_SUCCESS on success
858 * NDIS_STATUS_FAILURE on failure
859 * KeyName holds the name of the opened key
860 * KeyHandle holds a handle to the new key
863 KEY_BASIC_INFORMATION
*KeyInformation
;
864 ULONG KeyInformationLength
;
865 OBJECT_ATTRIBUTES KeyAttributes
;
866 NDIS_HANDLE RegKeyHandle
;
867 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
;
871 *Status
= ZwEnumerateKey(ConfigurationHandle
, Index
, KeyBasicInformation
, NULL
, 0, &KeyInformationLength
);
872 if(*Status
!= STATUS_BUFFER_TOO_SMALL
&& *Status
!= STATUS_BUFFER_OVERFLOW
&& *Status
!= STATUS_SUCCESS
)
874 NDIS_DbgPrint(MIN_TRACE
, ("ZwEnumerateKey failed (%x)\n", *Status
));
875 *Status
= NDIS_STATUS_FAILURE
;
879 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
+ sizeof(KEY_BASIC_INFORMATION
));
882 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
883 *Status
= NDIS_STATUS_FAILURE
;
887 *Status
= ZwEnumerateKey(ConfigurationHandle
, Index
, KeyBasicInformation
, KeyInformation
,
888 KeyInformationLength
+ sizeof(KEY_BASIC_INFORMATION
), &KeyInformationLength
);
890 if(*Status
!= STATUS_SUCCESS
)
892 NDIS_DbgPrint(MIN_TRACE
, ("ZwEnumerateKey failed (%x)\n", *Status
));
893 ExFreePool(KeyInformation
);
894 *Status
= NDIS_STATUS_FAILURE
;
898 /* should i fail instead if the passed-in string isn't long enough? */
899 wcsncpy(KeyName
->Buffer
, KeyInformation
->Name
, KeyName
->MaximumLength
/sizeof(WCHAR
));
900 KeyName
->Length
= (USHORT
)min(KeyInformation
->NameLength
, KeyName
->MaximumLength
);
902 InitializeObjectAttributes(&KeyAttributes
, KeyName
, OBJ_CASE_INSENSITIVE
, ConfigurationHandle
, NULL
);
904 *Status
= ZwOpenKey(&RegKeyHandle
, KEY_ALL_ACCESS
, &KeyAttributes
);
906 ExFreePool(KeyInformation
);
908 if(*Status
!= STATUS_SUCCESS
)
910 NDIS_DbgPrint(MIN_TRACE
, ("ZwOpenKey failed (%x)\n", *Status
));
911 *Status
= NDIS_STATUS_FAILURE
;
915 ConfigurationContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_CONFIGURATION_CONTEXT
));
916 if(!ConfigurationContext
)
918 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
919 ZwClose(RegKeyHandle
);
920 *Status
= NDIS_STATUS_FAILURE
;
924 KeInitializeSpinLock(&ConfigurationContext
->ResourceLock
);
925 InitializeListHead(&ConfigurationContext
->ResourceListHead
);
927 ConfigurationContext
->Handle
= RegKeyHandle
;
929 *KeyHandle
= (NDIS_HANDLE
)ConfigurationContext
;
931 *Status
= NDIS_STATUS_SUCCESS
;
940 NdisOpenConfigurationKeyByName(
941 OUT PNDIS_STATUS Status
,
942 IN NDIS_HANDLE ConfigurationHandle
,
943 IN PNDIS_STRING KeyName
,
944 OUT PNDIS_HANDLE KeyHandle
)
946 * FUNCTION: Opens a configuration subkey by name
948 * Status: points to an NDIS_STATUS where status is returned
949 * ConfigurationHandle: handle returned by a previous open call
950 * KeyName: the name of the key to open
951 * KeyHandle: a handle to the opened key
953 * NDIS_STATUS_SUCCESS on success
954 * NDIS_STATUS_FAILURE on failure
955 * KeyHandle holds a handle to the newly-opened key
959 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
;
960 OBJECT_ATTRIBUTES KeyAttributes
;
961 NDIS_HANDLE RegKeyHandle
;
965 InitializeObjectAttributes(&KeyAttributes
, KeyName
, OBJ_CASE_INSENSITIVE
, ConfigurationHandle
, 0);
966 *Status
= ZwOpenKey(&RegKeyHandle
, KEY_ALL_ACCESS
, &KeyAttributes
);
968 if(*Status
!= STATUS_SUCCESS
)
970 NDIS_DbgPrint(MIN_TRACE
, ("ZwOpenKey failed (%x)\n", *Status
));
971 *Status
= NDIS_STATUS_FAILURE
;
975 ConfigurationContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_CONFIGURATION_CONTEXT
));
976 if(!ConfigurationContext
)
978 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
979 ZwClose(RegKeyHandle
);
980 *Status
= NDIS_STATUS_FAILURE
;
984 KeInitializeSpinLock(&ConfigurationContext
->ResourceLock
);
985 InitializeListHead(&ConfigurationContext
->ResourceListHead
);
987 ConfigurationContext
->Handle
= RegKeyHandle
;
989 *KeyHandle
= (NDIS_HANDLE
)ConfigurationContext
;
991 *Status
= NDIS_STATUS_SUCCESS
;