- Big debugging update
[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 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
72
73 /* reset parameter type to standard reg types */
74 switch(ParameterType)
75 {
76 case NdisParameterHexInteger:
77 case NdisParameterInteger:
78 {
79 UNICODE_STRING Str;
80
81 Str.Buffer = (PWSTR) &Buff;
82 Str.MaximumLength = (USHORT)sizeof(Buff);
83 Str.Length = 0;
84
85 ParameterType = REG_SZ;
86 if (!NT_SUCCESS(RtlIntegerToUnicodeString(
87 ParameterValue->ParameterData.IntegerData,
88 (ParameterType == NdisParameterInteger) ? 10 : 16, &Str)))
89 {
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 = REG_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
327 *ParameterValue = NULL;
328 *Status = NDIS_STATUS_FAILURE;
329
330 if(ParameterType != NdisParameterInteger &&
331 ParameterType != NdisParameterHexInteger &&
332 ParameterType != NdisParameterString &&
333 ParameterType != NdisParameterMultiString &&
334 ParameterType != NdisParameterBinary
335 )
336 {
337 NDIS_DbgPrint(MIN_TRACE,("unsupported parameter type\n"));
338 *Status = NDIS_STATUS_NOT_SUPPORTED;
339 return;
340 }
341
342 NDIS_DbgPrint(MAX_TRACE,("requested read of %wZ\n", Keyword));
343
344 if (ConfigurationContext == NULL)
345 {
346 NDIS_DbgPrint(MIN_TRACE,("invalid parameter ConfigurationContext (0x%x)\n",ConfigurationContext));
347 return;
348 }
349
350 if(
351 !wcsncmp(Keyword->Buffer, L"Environment", Keyword->Length/sizeof(WCHAR)) &&
352 wcslen(L"Environment") == Keyword->Length/sizeof(WCHAR)
353 )
354 {
355 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
356 if(!*ParameterValue)
357 {
358 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
359 *Status = NDIS_STATUS_RESOURCES;
360 return;
361 }
362
363 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
364 if(!MiniportResource)
365 {
366 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
367 ExFreePool(*ParameterValue);
368 *ParameterValue = NULL;
369 *Status = NDIS_STATUS_RESOURCES;
370 return;
371 }
372
373 MiniportResource->ResourceType = 0;
374 MiniportResource->Resource = *ParameterValue;
375
376 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n",
377 MiniportResource->Resource));
378
379 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
380 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
381
382 (*ParameterValue)->ParameterType = NdisParameterInteger;
383 (*ParameterValue)->ParameterData.IntegerData = NdisEnvironmentWindowsNt;
384 *Status = NDIS_STATUS_SUCCESS;
385
386 return;
387 }
388
389 if(
390 !wcsncmp(Keyword->Buffer, L"ProcessorType", Keyword->Length/sizeof(WCHAR)) &&
391 wcslen(L"ProcessorType") == Keyword->Length/sizeof(WCHAR)
392 )
393 {
394 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
395 if(!*ParameterValue)
396 {
397 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
398 *Status = NDIS_STATUS_RESOURCES;
399 return;
400 }
401
402 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
403 if(!MiniportResource)
404 {
405 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
406 ExFreePool(*ParameterValue);
407 *ParameterValue = NULL;
408 *Status = NDIS_STATUS_RESOURCES;
409 return;
410 }
411
412 MiniportResource->ResourceType = 0;
413 MiniportResource->Resource = *ParameterValue;
414 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
415 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
416 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
417
418 (*ParameterValue)->ParameterType = NdisParameterInteger;
419 (*ParameterValue)->ParameterData.IntegerData = NdisProcessorX86; /* XXX non-portable */
420 *Status = NDIS_STATUS_SUCCESS;
421
422 return;
423 }
424
425 if(
426 !wcsncmp(Keyword->Buffer, L"NdisVersion", Keyword->Length/sizeof(WCHAR)) &&
427 wcslen(L"NdisVersion") == Keyword->Length/sizeof(WCHAR)
428 )
429 {
430 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
431 if(!*ParameterValue)
432 {
433 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
434 *Status = NDIS_STATUS_RESOURCES;
435 return;
436 }
437
438 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
439 if(!MiniportResource)
440 {
441 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
442 ExFreePool(*ParameterValue);
443 *ParameterValue = NULL;
444 *Status = NDIS_STATUS_RESOURCES;
445 return;
446 }
447
448 MiniportResource->ResourceType = 0;
449 MiniportResource->Resource = *ParameterValue;
450 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
451 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead,
452 &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
453
454 (*ParameterValue)->ParameterType = NdisParameterInteger;
455 (*ParameterValue)->ParameterData.IntegerData = NDIS_VERSION;
456 *Status = NDIS_STATUS_SUCCESS;
457
458 NDIS_DbgPrint(MAX_TRACE,("ParameterType = %0x%x, ParameterValue = 0x%x\n",
459 (*ParameterValue)->ParameterType, (*ParameterValue)->ParameterData.IntegerData));
460 return;
461 }
462
463 /* figure out how much buffer i should allocate */
464 *Status = ZwQueryValueKey(ConfigurationContext->Handle, Keyword, KeyValuePartialInformation, NULL, 0, &KeyDataLength);
465 if(*Status != STATUS_BUFFER_OVERFLOW && *Status != STATUS_BUFFER_TOO_SMALL && *Status != STATUS_SUCCESS)
466 {
467 NDIS_DbgPrint(MIN_TRACE,("ZwQueryValueKey #1 failed for %wZ, status 0x%x\n", Keyword, *Status));
468 *Status = NDIS_STATUS_FAILURE;
469 return;
470 }
471
472 /* allocate it */
473 KeyInformation = ExAllocatePool(PagedPool, KeyDataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION));
474 if(!KeyInformation)
475 {
476 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
477 *Status = NDIS_STATUS_RESOURCES;
478 return;
479 }
480
481 /* grab the value */
482 *Status = ZwQueryValueKey(ConfigurationContext->Handle, Keyword, KeyValuePartialInformation,
483 KeyInformation, KeyDataLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION), &KeyDataLength);
484 if(*Status != STATUS_SUCCESS)
485 {
486 ExFreePool(KeyInformation);
487 NDIS_DbgPrint(MIN_TRACE,("ZwQueryValueKey #2 failed for %wZ, status 0x%x\n", Keyword, *Status));
488 *Status = NDIS_STATUS_FAILURE;
489 return;
490 }
491
492 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
493 if(!MiniportResource)
494 {
495 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
496 ExFreePool(KeyInformation);
497 *Status = NDIS_STATUS_RESOURCES;
498 return;
499 }
500
501 switch(ParameterType)
502 {
503 case NdisParameterInteger:
504 case NdisParameterHexInteger:
505 {
506 UNICODE_STRING str;
507
508 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
509 if(!*ParameterValue)
510 {
511 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
512 ExFreePool(KeyInformation);
513 *Status = NDIS_STATUS_RESOURCES;
514 return;
515 }
516
517 str.Length = str.MaximumLength = (USHORT)KeyInformation->DataLength;
518 str.Buffer = (PWCHAR)KeyInformation->Data;
519
520 (*ParameterValue)->ParameterType = ParameterType;
521
522 /*
523 If ParameterType is NdisParameterInteger then the base of str is decimal.
524 If ParameterType is NdisParameterHexInteger then the base of str is hexadecimal.
525 */
526 if (ParameterType == NdisParameterInteger)
527 *Status = RtlUnicodeStringToInteger(&str, 10, &(*ParameterValue)->ParameterData.IntegerData);
528 else if (ParameterType == NdisParameterHexInteger)
529 *Status = RtlUnicodeStringToInteger(&str, 16, &(*ParameterValue)->ParameterData.IntegerData);
530
531
532 ExFreePool(KeyInformation);
533
534 if(*Status != STATUS_SUCCESS) {
535 ExFreePool(*ParameterValue);
536 *ParameterValue = NULL;
537 *Status = NDIS_STATUS_FAILURE;
538 return;
539 }
540
541 MiniportResource->ResourceType = 0;
542 MiniportResource->Resource = *ParameterValue;
543 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
544 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
545
546 *Status = NDIS_STATUS_SUCCESS;
547
548 return;
549 }
550
551 case NdisParameterString:
552 case NdisParameterMultiString:
553 {
554 PWCHAR RegData = 0;
555
556 if(KeyInformation->Type != REG_SZ && KeyInformation->Type != REG_MULTI_SZ)
557 {
558 NDIS_DbgPrint(MIN_TRACE,("requested type does not match actual value type\n"));
559 ExFreePool(KeyInformation);
560 *ParameterValue = NULL;
561 *Status = NDIS_STATUS_FAILURE;
562 return;
563 }
564
565 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER));
566 if(!*ParameterValue)
567 {
568 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
569 ExFreePool(KeyInformation);
570 *Status = NDIS_STATUS_RESOURCES;
571 return;
572 }
573
574 RegData = ExAllocatePool(PagedPool, KeyInformation->DataLength);
575 if(!RegData)
576 {
577 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
578 ExFreePool(KeyInformation);
579 ExFreePool(*ParameterValue);
580 *ParameterValue = NULL;
581 *Status = NDIS_STATUS_FAILURE;
582 return;
583 }
584
585 MiniportResource->ResourceType = 0;
586 MiniportResource->Resource = *ParameterValue;
587 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
588 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
589
590 memcpy(RegData, KeyInformation->Data, KeyInformation->DataLength);
591
592 (*ParameterValue)->ParameterType = ParameterType;
593 (*ParameterValue)->ParameterData.StringData.Length = (USHORT)KeyInformation->DataLength;
594 (*ParameterValue)->ParameterData.StringData.Buffer = RegData;
595
596 ExFreePool(KeyInformation);
597
598 *Status = NDIS_STATUS_SUCCESS;
599
600 return;
601 }
602
603 case NdisParameterBinary:
604 {
605 if(KeyInformation->Type != REG_BINARY)
606 {
607 NDIS_DbgPrint(MIN_TRACE,("requested type does not match actual value type\n"));
608 *Status = NDIS_STATUS_FAILURE;
609 ExFreePool(KeyInformation);
610 return;
611 }
612
613 *ParameterValue = ExAllocatePool(PagedPool, sizeof(NDIS_CONFIGURATION_PARAMETER) + KeyInformation->DataLength);
614 if(!*ParameterValue)
615 {
616 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
617 ExFreePool(KeyInformation);
618 *Status = NDIS_STATUS_RESOURCES;
619 return;
620 }
621
622 (*ParameterValue)->ParameterData.BinaryData.Buffer = ExAllocatePool(PagedPool, KeyInformation->DataLength);
623 if (!(*ParameterValue)->ParameterData.BinaryData.Buffer)
624 {
625 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
626 ExFreePool(KeyInformation);
627 *Status = NDIS_STATUS_RESOURCES;
628 return;
629 }
630
631 (*ParameterValue)->ParameterType = ParameterType;
632 (*ParameterValue)->ParameterData.BinaryData.Length = KeyInformation->DataLength;
633 memcpy((*ParameterValue)->ParameterData.BinaryData.Buffer, KeyInformation->Data, KeyInformation->DataLength);
634
635 MiniportResource->ResourceType = 0;
636 MiniportResource->Resource = *ParameterValue;
637 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
638 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
639
640 ExFreePool(KeyInformation);
641
642 *Status = NDIS_STATUS_SUCCESS;
643
644 return;
645 }
646 }
647 }
648
649
650 UCHAR UnicodeToHexByte(WCHAR chr)
651 /*
652 * FUNCTION: Converts a unicode hex character to its numerical value
653 * ARGUMENTS:
654 * chr: Unicode character to convert
655 * RETURNS:
656 * The numerical value of chr
657 */
658 {
659 switch(chr)
660 {
661 case L'0': return 0;
662 case L'1': return 1;
663 case L'2': return 2;
664 case L'3': return 3;
665 case L'4': return 4;
666 case L'5': return 5;
667 case L'6': return 6;
668 case L'7': return 7;
669 case L'8': return 8;
670 case L'9': return 9;
671 case L'A':
672 case L'a':
673 return 10;
674 case L'B':
675 case L'b':
676 return 11;
677 case L'C':
678 case L'c':
679 return 12;
680 case L'D':
681 case L'd':
682 return 13;
683 case L'E':
684 case L'e':
685 return 14;
686 case L'F':
687 case L'f':
688 return 15;
689 }
690 return -1;
691 }
692
693
694 /*
695 * @implemented
696 */
697 VOID
698 EXPORT
699 NdisReadNetworkAddress(
700 OUT PNDIS_STATUS Status,
701 OUT PVOID * NetworkAddress,
702 OUT PUINT NetworkAddressLength,
703 IN NDIS_HANDLE ConfigurationHandle)
704 /*
705 * FUNCTION: Reads the network address from the registry
706 * ARGUMENTS:
707 * Status - variable to receive status
708 * NetworkAddress - pointer to a buffered network address array
709 * NetworkAddressLength - length of the NetworkAddress array
710 * ConfigurationHandle: handle passed back from one of the open routines
711 * RETURNS:
712 * NDIS_STATUS_SUCCESS on success
713 * NDIS_STATUS_FAILURE on failure
714 * The network address is placed in the NetworkAddress buffer
715 */
716 {
717 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext = (PMINIPORT_CONFIGURATION_CONTEXT)ConfigurationHandle;
718 PMINIPORT_RESOURCE MiniportResource = NULL;
719 PNDIS_CONFIGURATION_PARAMETER ParameterValue = NULL;
720 NDIS_STRING Keyword;
721 UINT *IntArray = 0;
722 UINT i,j = 0;
723
724 NdisInitUnicodeString(&Keyword, L"NetworkAddress");
725 NdisReadConfiguration(Status, &ParameterValue, ConfigurationHandle, &Keyword, NdisParameterString);
726 if(*Status != NDIS_STATUS_SUCCESS)
727 {
728 NDIS_DbgPrint(MIN_TRACE, ("NdisReadConfiguration failed (%x)\n", *Status));
729 *Status = NDIS_STATUS_FAILURE;
730 return;
731 }
732
733 while (ParameterValue->ParameterData.StringData.Buffer[j] != '\0') j++;
734
735 *NetworkAddressLength = (UINT)((j/2)+0.5);
736
737 if (j == 0)
738 {
739 NDIS_DbgPrint(MIN_TRACE,("Empty NetworkAddress registry entry.\n"));
740 *Status = NDIS_STATUS_FAILURE;
741 return;
742 }
743
744 IntArray = ExAllocatePool(PagedPool, (*NetworkAddressLength)*sizeof(UINT));
745 if(!IntArray)
746 {
747 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
748 *Status = NDIS_STATUS_RESOURCES;
749 return;
750 }
751
752 MiniportResource = ExAllocatePool(PagedPool, sizeof(MINIPORT_RESOURCE));
753 if(!MiniportResource)
754 {
755 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
756 ExFreePool(IntArray);
757 *Status = NDIS_STATUS_RESOURCES;
758 return;
759 }
760
761 MiniportResource->ResourceType = 0;
762 MiniportResource->Resource = IntArray;
763 NDIS_DbgPrint(MID_TRACE,("inserting 0x%x into the resource list\n", MiniportResource->Resource));
764 ExInterlockedInsertTailList(&ConfigurationContext->ResourceListHead, &MiniportResource->ListEntry, &ConfigurationContext->ResourceLock);
765
766 /* convert from string to bytes */
767 for(i=0; i<(*NetworkAddressLength); i++)
768 {
769 IntArray[i] = (UnicodeToHexByte((ParameterValue->ParameterData.StringData.Buffer)[2*i]) << 4) +
770 UnicodeToHexByte((ParameterValue->ParameterData.StringData.Buffer)[2*i+1]);
771 }
772
773 *NetworkAddress = IntArray;
774
775 *Status = NDIS_STATUS_SUCCESS;
776 }
777
778
779 /*
780 * @implemented
781 */
782 VOID
783 EXPORT
784 NdisOpenConfigurationKeyByIndex(
785 OUT PNDIS_STATUS Status,
786 IN NDIS_HANDLE ConfigurationHandle,
787 IN ULONG Index,
788 OUT PNDIS_STRING KeyName,
789 OUT PNDIS_HANDLE KeyHandle)
790 /*
791 * FUNCTION: Opens a configuration subkey by index number
792 * ARGUMENTS:
793 * Status: pointer to an NDIS_STATUS to receive status info
794 * ConfigurationHandle: the handle passed back from a previous open function
795 * Index: the zero-based index of the subkey to open
796 * KeyName: the name of the key that was opened
797 * KeyHandle: a handle to the key that was opened
798 * RETURNS:
799 * NDIS_STATUS_SUCCESS on success
800 * NDIS_STATUS_FAILURE on failure
801 * KeyName holds the name of the opened key
802 * KeyHandle holds a handle to the new key
803 */
804 {
805 KEY_BASIC_INFORMATION *KeyInformation;
806 ULONG KeyInformationLength;
807 OBJECT_ATTRIBUTES KeyAttributes;
808 NDIS_HANDLE RegKeyHandle;
809 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
810
811 *KeyHandle = NULL;
812
813 *Status = ZwEnumerateKey(ConfigurationHandle, Index, KeyBasicInformation, NULL, 0, &KeyInformationLength);
814 if(*Status != STATUS_BUFFER_TOO_SMALL && *Status != STATUS_BUFFER_OVERFLOW && *Status != STATUS_SUCCESS)
815 {
816 NDIS_DbgPrint(MIN_TRACE, ("ZwEnumerateKey failed (%x)\n", *Status));
817 *Status = NDIS_STATUS_FAILURE;
818 return;
819 }
820
821 KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength + sizeof(KEY_BASIC_INFORMATION));
822 if(!KeyInformation)
823 {
824 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
825 *Status = NDIS_STATUS_FAILURE;
826 return;
827 }
828
829 *Status = ZwEnumerateKey(ConfigurationHandle, Index, KeyBasicInformation, KeyInformation,
830 KeyInformationLength + sizeof(KEY_BASIC_INFORMATION), &KeyInformationLength);
831
832 if(*Status != STATUS_SUCCESS)
833 {
834 NDIS_DbgPrint(MIN_TRACE, ("ZwEnumerateKey failed (%x)\n", *Status));
835 ExFreePool(KeyInformation);
836 *Status = NDIS_STATUS_FAILURE;
837 return;
838 }
839
840 /* should i fail instead if the passed-in string isn't long enough? */
841 wcsncpy(KeyName->Buffer, KeyInformation->Name, KeyName->MaximumLength/sizeof(WCHAR));
842 KeyName->Length = (USHORT)KeyInformation->NameLength;
843
844 InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE, ConfigurationHandle, NULL);
845
846 *Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
847
848 ExFreePool(KeyInformation);
849
850 if(*Status != STATUS_SUCCESS)
851 {
852 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
853 *Status = NDIS_STATUS_FAILURE;
854 return;
855 }
856
857 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
858 if(!ConfigurationContext)
859 {
860 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
861 ZwClose(RegKeyHandle);
862 *Status = NDIS_STATUS_FAILURE;
863 return;
864 }
865
866 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
867 InitializeListHead(&ConfigurationContext->ResourceListHead);
868
869 ConfigurationContext->Handle = RegKeyHandle;
870
871 *KeyHandle = (NDIS_HANDLE)ConfigurationContext;
872
873 *Status = NDIS_STATUS_SUCCESS;
874 }
875
876
877 /*
878 * @implemented
879 */
880 VOID
881 EXPORT
882 NdisOpenConfigurationKeyByName(
883 OUT PNDIS_STATUS Status,
884 IN NDIS_HANDLE ConfigurationHandle,
885 IN PNDIS_STRING KeyName,
886 OUT PNDIS_HANDLE KeyHandle)
887 /*
888 * FUNCTION: Opens a configuration subkey by name
889 * ARGUMENTS:
890 * Status: points to an NDIS_STATUS where status is returned
891 * ConfigurationHandle: handle returned by a previous open call
892 * KeyName: the name of the key to open
893 * KeyHandle: a handle to the opened key
894 * RETURNS:
895 * NDIS_STATUS_SUCCESS on success
896 * NDIS_STATUS_FAILURE on failure
897 * KeyHandle holds a handle to the newly-opened key
898 * NOTES:
899 */
900 {
901 PMINIPORT_CONFIGURATION_CONTEXT ConfigurationContext;
902 OBJECT_ATTRIBUTES KeyAttributes;
903 NDIS_HANDLE RegKeyHandle;
904
905 *KeyHandle = NULL;
906
907 InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE, ConfigurationHandle, 0);
908 *Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
909
910 if(*Status != STATUS_SUCCESS)
911 {
912 NDIS_DbgPrint(MIN_TRACE, ("ZwOpenKey failed (%x)\n", *Status));
913 *Status = NDIS_STATUS_FAILURE;
914 return;
915 }
916
917 ConfigurationContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_CONFIGURATION_CONTEXT));
918 if(!ConfigurationContext)
919 {
920 NDIS_DbgPrint(MIN_TRACE,("Insufficient resources.\n"));
921 ZwClose(RegKeyHandle);
922 *Status = NDIS_STATUS_FAILURE;
923 return;
924 }
925
926 KeInitializeSpinLock(&ConfigurationContext->ResourceLock);
927 InitializeListHead(&ConfigurationContext->ResourceListHead);
928
929 ConfigurationContext->Handle = RegKeyHandle;
930
931 *KeyHandle = (NDIS_HANDLE)ConfigurationContext;
932
933 *Status = NDIS_STATUS_SUCCESS;
934 }