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