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