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