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
38 #define PARAMETERS_KEY L"Parameters" /* The parameters subkey under the device-specific key */
45 NdisWriteConfiguration(
46 OUT PNDIS_STATUS Status
,
47 IN NDIS_HANDLE ConfigurationHandle
,
48 IN PNDIS_STRING Keyword
,
49 IN PNDIS_CONFIGURATION_PARAMETER ParameterValue
)
51 * FUNCTION: Writes a configuration value to the registry
53 * Status: Pointer to a caller-supplied NDIS_STATUS where we return status
54 * ConfigurationHandle: The Configuration Handle passed back from the call to one of the Open functions
55 * Keyword: The registry value name to write
56 * ParameterValue: The value data to write
58 * NDIS_STATUS_SUCCESS - the operation completed successfully
59 * NDIS_STATUS_NOT_SUPPORTED - The parameter type is not supported
60 * NDIS_STATUS_RESOURCES - out of memory, etc.
61 * NDIS_STATUS_FAILURE - any other failure
63 * There's a cryptic comment in the ddk implying that this function allocates and keeps memory.
64 * I don't know why tho so i free everything before return. comments welcome.
72 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
74 NDIS_DbgPrint(MID_TRACE
, ("Parameter type: %d\n", ParameterValue
->ParameterType
));
76 /* reset parameter type to standard reg types */
77 switch(ParameterValue
->ParameterType
)
79 case NdisParameterHexInteger
:
80 case NdisParameterInteger
:
84 Str
.Buffer
= (PWSTR
) &Buff
;
85 Str
.MaximumLength
= (USHORT
)sizeof(Buff
);
88 ParameterType
= REG_SZ
;
89 if (!NT_SUCCESS(RtlIntegerToUnicodeString(
90 ParameterValue
->ParameterData
.IntegerData
,
91 (ParameterValue
->ParameterType
== NdisParameterInteger
) ? 10 : 16, &Str
)))
93 NDIS_DbgPrint(MIN_TRACE
, ("RtlIntegerToUnicodeString failed (%x)\n", *Status
));
94 *Status
= NDIS_STATUS_FAILURE
;
98 DataSize
= Str
.Length
;
101 case NdisParameterString
:
102 case NdisParameterMultiString
:
103 ParameterType
= (ParameterValue
->ParameterType
== NdisParameterString
) ? REG_SZ
: REG_MULTI_SZ
;
104 Data
= ParameterValue
->ParameterData
.StringData
.Buffer
;
105 DataSize
= ParameterValue
->ParameterData
.StringData
.Length
;
108 /* New (undocumented) addition to 2k ddk */
109 case NdisParameterBinary
:
110 ParameterType
= REG_BINARY
;
111 Data
= ParameterValue
->ParameterData
.BinaryData
.Buffer
;
112 DataSize
= ParameterValue
->ParameterData
.BinaryData
.Length
;
116 *Status
= NDIS_STATUS_NOT_SUPPORTED
;
120 *Status
= ZwSetValueKey(((PMINIPORT_CONFIGURATION_CONTEXT
)ConfigurationHandle
)->Handle
,
121 Keyword
, 0, ParameterType
, Data
, DataSize
);
123 if(*Status
!= STATUS_SUCCESS
) {
124 NDIS_DbgPrint(MIN_TRACE
, ("ZwSetValueKey failed (%x)\n", *Status
));
125 *Status
= NDIS_STATUS_FAILURE
;
127 *Status
= NDIS_STATUS_SUCCESS
;
136 NdisCloseConfiguration(
137 IN NDIS_HANDLE ConfigurationHandle
)
139 * FUNCTION: Closes handles and releases per-handle resources
141 * ConfigurationHandle - pointer to the context with the resources to free
144 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
= (PMINIPORT_CONFIGURATION_CONTEXT
)ConfigurationHandle
;
145 PMINIPORT_RESOURCE Resource
;
146 PNDIS_CONFIGURATION_PARAMETER ParameterValue
;
147 PLIST_ENTRY CurrentEntry
;
149 while((CurrentEntry
= ExInterlockedRemoveHeadList(&ConfigurationContext
->ResourceListHead
,
150 &ConfigurationContext
->ResourceLock
)) != NULL
)
152 Resource
= CONTAINING_RECORD(CurrentEntry
, MINIPORT_RESOURCE
, ListEntry
);
153 switch(Resource
->ResourceType
)
155 case MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
:
156 ParameterValue
= Resource
->Resource
;
158 switch (ParameterValue
->ParameterType
)
160 case NdisParameterBinary
:
161 ExFreePool(ParameterValue
->ParameterData
.BinaryData
.Buffer
);
164 case NdisParameterString
:
165 case NdisParameterMultiString
:
166 ExFreePool(ParameterValue
->ParameterData
.StringData
.Buffer
);
173 /* Fall through to free NDIS_CONFIGURATION_PARAMETER struct */
175 case MINIPORT_RESOURCE_TYPE_MEMORY
:
176 NDIS_DbgPrint(MAX_TRACE
,("freeing 0x%x\n", Resource
->Resource
));
177 ExFreePool(Resource
->Resource
);
181 NDIS_DbgPrint(MIN_TRACE
,("Unknown resource type: %d\n", Resource
->ResourceType
));
185 ExFreePool(Resource
);
188 ZwClose(ConfigurationContext
->Handle
);
197 NdisOpenConfiguration(
198 OUT PNDIS_STATUS Status
,
199 OUT PNDIS_HANDLE ConfigurationHandle
,
200 IN NDIS_HANDLE WrapperConfigurationContext
)
202 * FUNCTION: Opens the configuration key and sets up resource tracking for the returned handle
204 * Status: Pointer to a caller-supplied NDIS_STATUS that is filled in with a return value
205 * ConfigurationHandle: Pointer to an opaque configuration handle returned on success
206 * WrapperConfigurationContext: handle originally passed back from NdisInitializeWrapper
208 * NDIS_STATUS_SUCCESS: the operation completed successfully
209 * NDIS_STATUS_FAILURE: the operation failed
211 * I think this is the parameters key; please verify.
215 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
;
216 PNDIS_WRAPPER_CONTEXT WrapperContext
= (PNDIS_WRAPPER_CONTEXT
)WrapperConfigurationContext
;
217 HANDLE RootKeyHandle
= WrapperContext
->RegistryHandle
;
219 NDIS_DbgPrint(MAX_TRACE
, ("Called\n"));
221 *ConfigurationHandle
= NULL
;
223 *Status
= ZwDuplicateObject(NtCurrentProcess(), RootKeyHandle
,
224 NtCurrentProcess(), &KeyHandle
, 0, 0,
225 DUPLICATE_SAME_ACCESS
);
226 if(!NT_SUCCESS(*Status
))
228 NDIS_DbgPrint(MIN_TRACE
, ("Failed to open registry configuration for this miniport\n"));
229 *Status
= NDIS_STATUS_FAILURE
;
233 ConfigurationContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_CONFIGURATION_CONTEXT
));
234 if(!ConfigurationContext
)
236 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
238 *Status
= NDIS_STATUS_RESOURCES
;
242 KeInitializeSpinLock(&ConfigurationContext
->ResourceLock
);
243 InitializeListHead(&ConfigurationContext
->ResourceListHead
);
245 ConfigurationContext
->Handle
= KeyHandle
;
247 *ConfigurationHandle
= (NDIS_HANDLE
)ConfigurationContext
;
248 *Status
= NDIS_STATUS_SUCCESS
;
250 NDIS_DbgPrint(MAX_TRACE
,("returning success\n"));
259 NdisOpenProtocolConfiguration(
260 OUT PNDIS_STATUS Status
,
261 OUT PNDIS_HANDLE ConfigurationHandle
,
262 IN PNDIS_STRING ProtocolSection
)
264 * FUNCTION: Open the configuration key and set up resource tracking for the protocol
266 * Status: caller-allocated buffer where status is returned
267 * ConfigurationHandle: spot to return the opaque configuration context
268 * ProtocolSection: configuration string originally passed in to ProtocolBindAdapter
270 * NDIS_STATUS_SUCCESS: the operation was a success
271 * NDIS_STATUS_FAILURE: the operation was not a success
273 * I think this is the per-device (adapter) parameters\{ProtocolName} key; please verify.
276 OBJECT_ATTRIBUTES KeyAttributes
;
277 UNICODE_STRING KeyNameU
;
279 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
;
282 KeyNameU
.MaximumLength
= ProtocolSection
->Length
+ sizeof(PARAMETERS_KEY
) + sizeof(UNICODE_NULL
);
283 KeyNameU
.Buffer
= ExAllocatePool(PagedPool
, KeyNameU
.MaximumLength
);
286 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
287 *ConfigurationHandle
= NULL
;
288 *Status
= NDIS_STATUS_FAILURE
;
292 RtlCopyUnicodeString(&KeyNameU
, ProtocolSection
);
293 RtlAppendUnicodeToString(&KeyNameU
, PARAMETERS_KEY
);
294 InitializeObjectAttributes(&KeyAttributes
, &KeyNameU
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
296 *Status
= ZwOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &KeyAttributes
);
298 ExFreePool(KeyNameU
.Buffer
);
300 if(*Status
!= NDIS_STATUS_SUCCESS
)
302 NDIS_DbgPrint(MIN_TRACE
, ("ZwOpenKey failed (%x)\n", *Status
));
303 *ConfigurationHandle
= NULL
;
304 *Status
= NDIS_STATUS_FAILURE
;
308 ConfigurationContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_CONFIGURATION_CONTEXT
));
309 if(!ConfigurationContext
)
311 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
313 *ConfigurationHandle
= NULL
;
314 *Status
= NDIS_STATUS_FAILURE
;
318 KeInitializeSpinLock(&ConfigurationContext
->ResourceLock
);
319 InitializeListHead(&ConfigurationContext
->ResourceListHead
);
321 ConfigurationContext
->Handle
= KeyHandle
;
323 *ConfigurationHandle
= (NDIS_HANDLE
)ConfigurationContext
;
324 *Status
= NDIS_STATUS_SUCCESS
;
327 UCHAR
UnicodeToHexByte(WCHAR chr
)
329 * FUNCTION: Converts a unicode hex character to its numerical value
331 * chr: Unicode character to convert
333 * The numerical value of chr
371 IsValidNumericString(PNDIS_STRING String
, ULONG Base
)
373 * FUNCTION: Determines if a string is a valid number
375 * String: Unicode string to evaluate
377 * TRUE if it is valid, FALSE if not
382 /* I don't think this will ever happen, but we warn it if it does */
383 if (String
->Length
== 0)
385 NDIS_DbgPrint(MIN_TRACE
, ("Got an empty string; not sure what to do here\n"));
389 for (i
= 0; i
< String
->Length
/ sizeof(WCHAR
); i
++)
391 /* Skip any NULL characters we find */
392 if (String
->Buffer
[i
] == UNICODE_NULL
)
395 /* Make sure the character is valid for a numeric string of this base */
396 if (UnicodeToHexByte(String
->Buffer
[i
]) >= Base
)
409 NdisReadConfiguration(
410 OUT PNDIS_STATUS Status
,
411 OUT PNDIS_CONFIGURATION_PARAMETER
* ParameterValue
,
412 IN NDIS_HANDLE ConfigurationHandle
,
413 IN PNDIS_STRING Keyword
,
414 IN NDIS_PARAMETER_TYPE ParameterType
)
416 * FUNCTION: Read a configuration value from the registry, tracking its resources
418 * Status: points to a place to write status into
419 * ParameterValue: Pointer to receive a newly-allocated parameter structure
420 * ConfigurationHandle: handle originally returned by an open function
421 * Keyword: Value name to read, or one of the following constants:
422 * Environment - returns NdisEnvironmentWindowsNt
423 * ProcessorType - returns NdisProcessorX86 until more architectures are added
424 * NdisVersion - returns NDIS_VERSION
425 * ParameterType: the type of the value to be queried
427 * - A status in Status
428 * - A parameter value in ParameterValue
431 KEY_VALUE_PARTIAL_INFORMATION
*KeyInformation
;
433 PMINIPORT_RESOURCE MiniportResource
;
434 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
= (PMINIPORT_CONFIGURATION_CONTEXT
)ConfigurationHandle
;
437 //*ParameterValue = NULL;
438 *Status
= NDIS_STATUS_FAILURE
;
440 NDIS_DbgPrint(MAX_TRACE
,("requested read of %wZ\n", Keyword
));
441 NDIS_DbgPrint(MID_TRACE
,("requested parameter type: %d\n", ParameterType
));
443 if (ConfigurationContext
== NULL
)
445 NDIS_DbgPrint(MIN_TRACE
,("invalid parameter ConfigurationContext (0x%x)\n",ConfigurationContext
));
449 if(!wcsncmp(Keyword
->Buffer
, L
"Environment", Keyword
->Length
/sizeof(WCHAR
)) &&
450 wcslen(L
"Environment") == Keyword
->Length
/sizeof(WCHAR
))
452 *ParameterValue
= ExAllocatePool(PagedPool
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
455 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
456 *Status
= NDIS_STATUS_RESOURCES
;
460 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
461 if(!MiniportResource
)
463 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
464 ExFreePool(*ParameterValue
);
465 *ParameterValue
= NULL
;
466 *Status
= NDIS_STATUS_RESOURCES
;
470 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
;
471 MiniportResource
->Resource
= *ParameterValue
;
473 NDIS_DbgPrint(MID_TRACE
,("inserting 0x%x into the resource list\n",
474 MiniportResource
->Resource
));
476 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
,
477 &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
479 (*ParameterValue
)->ParameterType
= NdisParameterInteger
;
480 (*ParameterValue
)->ParameterData
.IntegerData
= NdisEnvironmentWindowsNt
;
481 *Status
= NDIS_STATUS_SUCCESS
;
486 if(!wcsncmp(Keyword
->Buffer
, L
"ProcessorType", Keyword
->Length
/sizeof(WCHAR
)) &&
487 wcslen(L
"ProcessorType") == Keyword
->Length
/sizeof(WCHAR
))
489 *ParameterValue
= ExAllocatePool(PagedPool
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
492 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
493 *Status
= NDIS_STATUS_RESOURCES
;
497 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
498 if(!MiniportResource
)
500 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
501 ExFreePool(*ParameterValue
);
502 *ParameterValue
= NULL
;
503 *Status
= NDIS_STATUS_RESOURCES
;
507 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
;
508 MiniportResource
->Resource
= *ParameterValue
;
509 NDIS_DbgPrint(MID_TRACE
,("inserting 0x%x into the resource list\n", MiniportResource
->Resource
));
510 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
,
511 &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
513 (*ParameterValue
)->ParameterType
= NdisParameterInteger
;
514 (*ParameterValue
)->ParameterData
.IntegerData
= NdisProcessorX86
; /* XXX non-portable */
515 *Status
= NDIS_STATUS_SUCCESS
;
520 if(!wcsncmp(Keyword
->Buffer
, L
"NdisVersion", Keyword
->Length
/sizeof(WCHAR
)) &&
521 wcslen(L
"NdisVersion") == Keyword
->Length
/sizeof(WCHAR
))
523 *ParameterValue
= ExAllocatePool(PagedPool
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
526 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
527 *Status
= NDIS_STATUS_RESOURCES
;
531 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
532 if(!MiniportResource
)
534 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
535 ExFreePool(*ParameterValue
);
536 *ParameterValue
= NULL
;
537 *Status
= NDIS_STATUS_RESOURCES
;
541 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
;
542 MiniportResource
->Resource
= *ParameterValue
;
543 NDIS_DbgPrint(MID_TRACE
,("inserting 0x%x into the resource list\n", MiniportResource
->Resource
));
544 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
,
545 &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
547 (*ParameterValue
)->ParameterType
= NdisParameterInteger
;
548 (*ParameterValue
)->ParameterData
.IntegerData
= NDIS_VERSION
;
549 *Status
= NDIS_STATUS_SUCCESS
;
551 NDIS_DbgPrint(MAX_TRACE
,("ParameterType = %0x%x, ParameterValue = 0x%x\n",
552 (*ParameterValue
)->ParameterType
, (*ParameterValue
)->ParameterData
.IntegerData
));
556 /* figure out how much buffer i should allocate */
557 *Status
= ZwQueryValueKey(ConfigurationContext
->Handle
, Keyword
, KeyValuePartialInformation
, NULL
, 0, &KeyDataLength
);
558 if(*Status
!= STATUS_BUFFER_OVERFLOW
&& *Status
!= STATUS_BUFFER_TOO_SMALL
&& *Status
!= STATUS_SUCCESS
)
560 NDIS_DbgPrint(MID_TRACE
,("ZwQueryValueKey #1 failed for %wZ, status 0x%x\n", Keyword
, *Status
));
561 *Status
= NDIS_STATUS_FAILURE
;
566 KeyInformation
= ExAllocatePool(PagedPool
, KeyDataLength
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION
));
569 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
570 *Status
= NDIS_STATUS_RESOURCES
;
575 *Status
= ZwQueryValueKey(ConfigurationContext
->Handle
, Keyword
, KeyValuePartialInformation
,
576 KeyInformation
, KeyDataLength
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION
), &KeyDataLength
);
577 if(*Status
!= STATUS_SUCCESS
)
579 ExFreePool(KeyInformation
);
580 NDIS_DbgPrint(MIN_TRACE
,("ZwQueryValueKey #2 failed for %wZ, status 0x%x\n", Keyword
, *Status
));
581 *Status
= NDIS_STATUS_FAILURE
;
585 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
586 if(!MiniportResource
)
588 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
589 ExFreePool(KeyInformation
);
590 *Status
= NDIS_STATUS_RESOURCES
;
594 *ParameterValue
= ExAllocatePool(PagedPool
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
595 if (!*ParameterValue
)
597 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
598 ExFreePool(MiniportResource
);
599 ExFreePool(KeyInformation
);
600 *Status
= NDIS_STATUS_RESOURCES
;
604 RtlZeroMemory(*ParameterValue
, sizeof(NDIS_CONFIGURATION_PARAMETER
));
606 if (KeyInformation
->Type
== REG_BINARY
)
608 NDIS_DbgPrint(MAX_TRACE
, ("NdisParameterBinary\n"));
610 (*ParameterValue
)->ParameterType
= NdisParameterBinary
;
612 Buffer
= ExAllocatePool(PagedPool
, KeyInformation
->DataLength
);
615 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
616 ExFreePool(MiniportResource
);
617 ExFreePool(KeyInformation
);
618 *Status
= NDIS_STATUS_RESOURCES
;
622 RtlCopyMemory(Buffer
, KeyInformation
->Data
, KeyInformation
->DataLength
);
624 (*ParameterValue
)->ParameterData
.BinaryData
.Buffer
= Buffer
;
625 (*ParameterValue
)->ParameterData
.BinaryData
.Length
= KeyInformation
->DataLength
;
627 else if (KeyInformation
->Type
== REG_MULTI_SZ
)
629 NDIS_DbgPrint(MAX_TRACE
, ("NdisParameterMultiString\n"));
631 (*ParameterValue
)->ParameterType
= NdisParameterMultiString
;
633 Buffer
= ExAllocatePool(PagedPool
, KeyInformation
->DataLength
);
636 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
637 ExFreePool(MiniportResource
);
638 ExFreePool(KeyInformation
);
639 *Status
= NDIS_STATUS_RESOURCES
;
643 RtlCopyMemory(Buffer
, KeyInformation
->Data
, KeyInformation
->DataLength
);
645 (*ParameterValue
)->ParameterData
.StringData
.Buffer
= Buffer
;
646 (*ParameterValue
)->ParameterData
.StringData
.Length
= KeyInformation
->DataLength
;
648 else if (KeyInformation
->Type
== REG_SZ
)
653 if (ParameterType
== NdisParameterInteger
)
655 else if (ParameterType
== NdisParameterHexInteger
)
660 str
.Length
= str
.MaximumLength
= (USHORT
)KeyInformation
->DataLength
;
661 str
.Buffer
= (PWCHAR
)KeyInformation
->Data
;
663 if (Base
!= 0 && IsValidNumericString(&str
, Base
))
665 *Status
= RtlUnicodeStringToInteger(&str
, Base
, &(*ParameterValue
)->ParameterData
.IntegerData
);
666 ASSERT(*Status
== STATUS_SUCCESS
);
668 NDIS_DbgPrint(MAX_TRACE
, ("NdisParameter(Hex)Integer\n"));
670 /* MSDN documents that this is returned for all integers, regardless of the ParameterType passed in */
671 (*ParameterValue
)->ParameterType
= NdisParameterInteger
;
675 NDIS_DbgPrint(MAX_TRACE
, ("NdisParameterString\n"));
677 (*ParameterValue
)->ParameterType
= NdisParameterString
;
679 Buffer
= ExAllocatePool(PagedPool
, KeyInformation
->DataLength
);
682 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
683 ExFreePool(MiniportResource
);
684 ExFreePool(KeyInformation
);
685 *Status
= NDIS_STATUS_RESOURCES
;
689 RtlCopyMemory(Buffer
, KeyInformation
->Data
, KeyInformation
->DataLength
);
691 (*ParameterValue
)->ParameterData
.StringData
.Buffer
= Buffer
;
692 (*ParameterValue
)->ParameterData
.StringData
.Length
= KeyInformation
->DataLength
;
697 NDIS_DbgPrint(MIN_TRACE
, ("Invalid type for NdisReadConfiguration (%d)\n", KeyInformation
->Type
));
698 NDIS_DbgPrint(MIN_TRACE
, ("Requested type: %d\n", ParameterType
));
699 NDIS_DbgPrint(MIN_TRACE
, ("Registry entry: %wZ\n", Keyword
));
700 *Status
= NDIS_STATUS_FAILURE
;
701 ExFreePool(KeyInformation
);
705 if (((*ParameterValue
)->ParameterType
!= ParameterType
) &&
706 !((ParameterType
== NdisParameterHexInteger
) && ((*ParameterValue
)->ParameterType
== NdisParameterInteger
)))
708 NDIS_DbgPrint(MIN_TRACE
, ("Parameter type mismatch! (Requested: %d | Received: %d)\n",
709 ParameterType
, (*ParameterValue
)->ParameterType
));
710 NDIS_DbgPrint(MIN_TRACE
, ("Registry entry: %wZ\n", Keyword
));
713 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_REGISTRY_DATA
;
714 MiniportResource
->Resource
= *ParameterValue
;
716 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
, &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
718 ExFreePool(KeyInformation
);
720 *Status
= NDIS_STATUS_SUCCESS
;
728 NdisReadNetworkAddress(
729 OUT PNDIS_STATUS Status
,
730 OUT PVOID
* NetworkAddress
,
731 OUT PUINT NetworkAddressLength
,
732 IN NDIS_HANDLE ConfigurationHandle
)
734 * FUNCTION: Reads the network address from the registry
736 * Status - variable to receive status
737 * NetworkAddress - pointer to a buffered network address array
738 * NetworkAddressLength - length of the NetworkAddress array
739 * ConfigurationHandle: handle passed back from one of the open routines
741 * NDIS_STATUS_SUCCESS on success
742 * NDIS_STATUS_FAILURE on failure
743 * The network address is placed in the NetworkAddress buffer
746 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
= (PMINIPORT_CONFIGURATION_CONTEXT
)ConfigurationHandle
;
747 PMINIPORT_RESOURCE MiniportResource
= NULL
;
748 PNDIS_CONFIGURATION_PARAMETER ParameterValue
= NULL
;
754 NdisInitUnicodeString(&Keyword
, L
"NetworkAddress");
755 NdisReadConfiguration(Status
, &ParameterValue
, ConfigurationHandle
, &Keyword
, NdisParameterString
);
756 if(*Status
!= NDIS_STATUS_SUCCESS
)
758 NDIS_DbgPrint(MID_TRACE
, ("NdisReadConfiguration failed (%x)\n", *Status
));
759 *Status
= NDIS_STATUS_FAILURE
;
763 if (ParameterValue
->ParameterType
== NdisParameterInteger
)
767 NDIS_DbgPrint(MAX_TRACE
, ("Read integer data %lx\n",
768 ParameterValue
->ParameterData
.IntegerData
));
771 str
.MaximumLength
= (USHORT
)sizeof(Buff
);
774 *Status
= RtlIntegerToUnicodeString(ParameterValue
->ParameterData
.IntegerData
,
778 if (*Status
!= NDIS_STATUS_SUCCESS
)
780 NDIS_DbgPrint(MIN_TRACE
, ("RtlIntegerToUnicodeString failed (%x)\n", *Status
));
781 *Status
= NDIS_STATUS_FAILURE
;
785 NDIS_DbgPrint(MAX_TRACE
, ("Converted integer data into %wZ\n", &str
));
789 ASSERT(ParameterValue
->ParameterType
== NdisParameterString
);
790 str
= ParameterValue
->ParameterData
.StringData
;
793 while (j
< str
.Length
&& str
.Buffer
[j
] != '\0') j
++;
795 *NetworkAddressLength
= (j
+1) >> 1;
797 if ((*NetworkAddressLength
) == 0)
799 NDIS_DbgPrint(MIN_TRACE
,("Empty NetworkAddress registry entry.\n"));
800 *Status
= NDIS_STATUS_FAILURE
;
804 IntArray
= ExAllocatePool(PagedPool
, (*NetworkAddressLength
)*sizeof(UINT
));
807 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
808 *Status
= NDIS_STATUS_RESOURCES
;
812 MiniportResource
= ExAllocatePool(PagedPool
, sizeof(MINIPORT_RESOURCE
));
813 if(!MiniportResource
)
815 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
816 ExFreePool(IntArray
);
817 *Status
= NDIS_STATUS_RESOURCES
;
821 MiniportResource
->ResourceType
= MINIPORT_RESOURCE_TYPE_MEMORY
;
822 MiniportResource
->Resource
= IntArray
;
823 NDIS_DbgPrint(MID_TRACE
,("inserting 0x%x into the resource list\n", MiniportResource
->Resource
));
824 ExInterlockedInsertTailList(&ConfigurationContext
->ResourceListHead
, &MiniportResource
->ListEntry
, &ConfigurationContext
->ResourceLock
);
826 /* convert from string to bytes */
827 for(i
=0; i
<(*NetworkAddressLength
); i
++)
829 IntArray
[i
] = (UnicodeToHexByte((str
.Buffer
)[2*i
]) << 4) +
830 UnicodeToHexByte((str
.Buffer
)[2*i
+1]);
833 *NetworkAddress
= IntArray
;
835 *Status
= NDIS_STATUS_SUCCESS
;
844 NdisOpenConfigurationKeyByIndex(
845 OUT PNDIS_STATUS Status
,
846 IN NDIS_HANDLE ConfigurationHandle
,
848 OUT PNDIS_STRING KeyName
,
849 OUT PNDIS_HANDLE KeyHandle
)
851 * FUNCTION: Opens a configuration subkey by index number
853 * Status: pointer to an NDIS_STATUS to receive status info
854 * ConfigurationHandle: the handle passed back from a previous open function
855 * Index: the zero-based index of the subkey to open
856 * KeyName: the name of the key that was opened
857 * KeyHandle: a handle to the key that was opened
859 * NDIS_STATUS_SUCCESS on success
860 * NDIS_STATUS_FAILURE on failure
861 * KeyName holds the name of the opened key
862 * KeyHandle holds a handle to the new key
865 KEY_BASIC_INFORMATION
*KeyInformation
;
866 ULONG KeyInformationLength
;
867 OBJECT_ATTRIBUTES KeyAttributes
;
868 NDIS_HANDLE RegKeyHandle
;
869 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
;
873 *Status
= ZwEnumerateKey(ConfigurationHandle
, Index
, KeyBasicInformation
, NULL
, 0, &KeyInformationLength
);
874 if(*Status
!= STATUS_BUFFER_TOO_SMALL
&& *Status
!= STATUS_BUFFER_OVERFLOW
&& *Status
!= STATUS_SUCCESS
)
876 NDIS_DbgPrint(MIN_TRACE
, ("ZwEnumerateKey failed (%x)\n", *Status
));
877 *Status
= NDIS_STATUS_FAILURE
;
881 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
+ sizeof(KEY_BASIC_INFORMATION
));
884 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
885 *Status
= NDIS_STATUS_FAILURE
;
889 *Status
= ZwEnumerateKey(ConfigurationHandle
, Index
, KeyBasicInformation
, KeyInformation
,
890 KeyInformationLength
+ sizeof(KEY_BASIC_INFORMATION
), &KeyInformationLength
);
892 if(*Status
!= STATUS_SUCCESS
)
894 NDIS_DbgPrint(MIN_TRACE
, ("ZwEnumerateKey failed (%x)\n", *Status
));
895 ExFreePool(KeyInformation
);
896 *Status
= NDIS_STATUS_FAILURE
;
900 /* should i fail instead if the passed-in string isn't long enough? */
901 wcsncpy(KeyName
->Buffer
, KeyInformation
->Name
, KeyName
->MaximumLength
/sizeof(WCHAR
));
902 KeyName
->Length
= (USHORT
)min(KeyInformation
->NameLength
, KeyName
->MaximumLength
);
904 InitializeObjectAttributes(&KeyAttributes
, KeyName
, OBJ_CASE_INSENSITIVE
, ConfigurationHandle
, NULL
);
906 *Status
= ZwOpenKey(&RegKeyHandle
, KEY_ALL_ACCESS
, &KeyAttributes
);
908 ExFreePool(KeyInformation
);
910 if(*Status
!= STATUS_SUCCESS
)
912 NDIS_DbgPrint(MIN_TRACE
, ("ZwOpenKey failed (%x)\n", *Status
));
913 *Status
= NDIS_STATUS_FAILURE
;
917 ConfigurationContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_CONFIGURATION_CONTEXT
));
918 if(!ConfigurationContext
)
920 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
921 ZwClose(RegKeyHandle
);
922 *Status
= NDIS_STATUS_FAILURE
;
926 KeInitializeSpinLock(&ConfigurationContext
->ResourceLock
);
927 InitializeListHead(&ConfigurationContext
->ResourceListHead
);
929 ConfigurationContext
->Handle
= RegKeyHandle
;
931 *KeyHandle
= (NDIS_HANDLE
)ConfigurationContext
;
933 *Status
= NDIS_STATUS_SUCCESS
;
942 NdisOpenConfigurationKeyByName(
943 OUT PNDIS_STATUS Status
,
944 IN NDIS_HANDLE ConfigurationHandle
,
945 IN PNDIS_STRING KeyName
,
946 OUT PNDIS_HANDLE KeyHandle
)
948 * FUNCTION: Opens a configuration subkey by name
950 * Status: points to an NDIS_STATUS where status is returned
951 * ConfigurationHandle: handle returned by a previous open call
952 * KeyName: the name of the key to open
953 * KeyHandle: a handle to the opened key
955 * NDIS_STATUS_SUCCESS on success
956 * NDIS_STATUS_FAILURE on failure
957 * KeyHandle holds a handle to the newly-opened key
961 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext
;
962 OBJECT_ATTRIBUTES KeyAttributes
;
963 NDIS_HANDLE RegKeyHandle
;
967 InitializeObjectAttributes(&KeyAttributes
, KeyName
, OBJ_CASE_INSENSITIVE
, ConfigurationHandle
, 0);
968 *Status
= ZwOpenKey(&RegKeyHandle
, KEY_ALL_ACCESS
, &KeyAttributes
);
970 if(*Status
!= STATUS_SUCCESS
)
972 NDIS_DbgPrint(MIN_TRACE
, ("ZwOpenKey failed (%x)\n", *Status
));
973 *Status
= NDIS_STATUS_FAILURE
;
977 ConfigurationContext
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_CONFIGURATION_CONTEXT
));
978 if(!ConfigurationContext
)
980 NDIS_DbgPrint(MIN_TRACE
,("Insufficient resources.\n"));
981 ZwClose(RegKeyHandle
);
982 *Status
= NDIS_STATUS_FAILURE
;
986 KeInitializeSpinLock(&ConfigurationContext
->ResourceLock
);
987 InitializeListHead(&ConfigurationContext
->ResourceListHead
);
989 ConfigurationContext
->Handle
= RegKeyHandle
;
991 *KeyHandle
= (NDIS_HANDLE
)ConfigurationContext
;
993 *Status
= NDIS_STATUS_SUCCESS
;