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