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