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