1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxRegistryAPI.cpp 8 9 Abstract: 10 11 This module implements registry access in the framework 12 13 Author: 14 15 16 17 Environment: 18 19 Both kernel and user mode 20 21 Revision History: 22 23 --*/ 24 25 #include "fxsupportpch.hpp" 26 27 extern "C" { 28 // #include "FxRegistryAPI.tmh" 29 #define RtlSizeTToULong RtlULongPtrToULong 30 } 31 32 extern "C" { 33 // 34 // Not in a public header that we can reach, but is documented 35 // 36 NTSYSAPI 37 NTSTATUS 38 NTAPI 39 ZwDeleteValueKey( 40 __in IN HANDLE Key, 41 __in IN PUNICODE_STRING ValueName 42 ); 43 } 44 45 46 // 47 // Extern "C" the entire file 48 // 49 extern "C" { 50 51 _Must_inspect_result_ 52 __drv_maxIRQL(PASSIVE_LEVEL) 53 NTSTATUS 54 STDCALL 55 WDFEXPORT(WdfRegistryOpenKey)( 56 __in 57 PWDF_DRIVER_GLOBALS DriverGlobals, 58 __in_opt 59 WDFKEY ParentKey, 60 __in 61 PCUNICODE_STRING KeyName, 62 __in 63 ACCESS_MASK DesiredAccess, 64 __in_opt 65 PWDF_OBJECT_ATTRIBUTES KeyAttributes, 66 __out 67 WDFKEY* Key 68 ) 69 { 70 DDI_ENTRY(); 71 72 FxRegKey* pKey; 73 PFX_DRIVER_GLOBALS pFxDriverGlobals; 74 NTSTATUS status; 75 WDFKEY keyHandle; 76 HANDLE parentHandle; 77 78 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); 79 keyHandle = NULL; 80 81 if (ParentKey != NULL) { 82 FxRegKey* pParent; 83 84 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals, 85 ParentKey, 86 FX_TYPE_REG_KEY, 87 (PVOID*) &pParent, 88 &pFxDriverGlobals); 89 90 parentHandle = pParent->GetHandle(); 91 } 92 else { 93 parentHandle = NULL; 94 95 // 96 // Get the parent's globals if it is present 97 // 98 if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(pFxDriverGlobals, 99 KeyAttributes))) { 100 FxObject* pParent; 101 102 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals, 103 KeyAttributes->ParentObject, 104 FX_TYPE_OBJECT, 105 (PVOID*)&pParent, 106 &pFxDriverGlobals); 107 } 108 } 109 110 FxPointerNotNull(pFxDriverGlobals, KeyName); 111 FxPointerNotNull(pFxDriverGlobals, Key); 112 113 *Key = NULL; 114 115 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 116 if (!NT_SUCCESS(status)) { 117 return status; 118 } 119 120 status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes); 121 if (!NT_SUCCESS(status)) { 122 return status; 123 } 124 125 status = FxValidateUnicodeString(pFxDriverGlobals, KeyName); 126 if (!NT_SUCCESS(status)) { 127 return status; 128 } 129 130 pKey = new (pFxDriverGlobals, KeyAttributes) FxRegKey(pFxDriverGlobals); 131 if (pKey == NULL) { 132 status = STATUS_INSUFFICIENT_RESOURCES; 133 134 DoTraceLevelMessage( 135 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 136 "Could not allocate memory for a WDFKEY, %!STATUS!", status); 137 138 return status; 139 } 140 141 status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle); 142 143 if (NT_SUCCESS(status)) { 144 status = pKey->Open(parentHandle, KeyName, DesiredAccess); 145 146 if (NT_SUCCESS(status)) { 147 *Key = keyHandle; 148 } 149 else { 150 DoTraceLevelMessage( 151 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 152 "new WDFKEY object open failed, %!STATUS!", status); 153 } 154 } 155 156 if (!NT_SUCCESS(status)) { 157 pKey->DeleteFromFailedCreate(); 158 pKey = NULL; 159 } 160 161 return status; 162 } 163 164 _Must_inspect_result_ 165 __drv_maxIRQL(PASSIVE_LEVEL) 166 NTSTATUS 167 STDCALL 168 WDFEXPORT(WdfRegistryCreateKey)( 169 __in 170 PWDF_DRIVER_GLOBALS DriverGlobals, 171 __in_opt 172 WDFKEY ParentKey, 173 __in 174 PCUNICODE_STRING KeyName, 175 __in 176 ACCESS_MASK DesiredAccess, 177 __in 178 ULONG CreateOptions, 179 __out_opt 180 PULONG CreateDisposition, 181 __in_opt 182 PWDF_OBJECT_ATTRIBUTES KeyAttributes, 183 __out 184 WDFKEY* Key 185 ) 186 { 187 DDI_ENTRY(); 188 189 PFX_DRIVER_GLOBALS pFxDriverGlobals; 190 FxRegKey* pKey; 191 NTSTATUS status; 192 WDFKEY keyHandle; 193 HANDLE parentHandle; 194 195 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); 196 197 if (ParentKey != NULL) { 198 FxRegKey* pParent; 199 200 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals, 201 ParentKey, 202 FX_TYPE_REG_KEY, 203 (PVOID*) &pParent, 204 &pFxDriverGlobals); 205 206 parentHandle = pParent->GetHandle(); 207 } 208 else { 209 parentHandle = NULL; 210 211 // 212 // Get the parent's globals if it is present 213 // 214 if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(pFxDriverGlobals, 215 KeyAttributes))) { 216 FxObject* pParent; 217 218 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals, 219 KeyAttributes->ParentObject, 220 FX_TYPE_OBJECT, 221 (PVOID*)&pParent, 222 &pFxDriverGlobals); 223 } 224 } 225 226 FxPointerNotNull(pFxDriverGlobals, KeyName); 227 FxPointerNotNull(pFxDriverGlobals, Key); 228 229 *Key = NULL; 230 keyHandle = NULL; 231 232 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 233 if (!NT_SUCCESS(status)) { 234 return status; 235 } 236 237 status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes); 238 if (!NT_SUCCESS(status)) { 239 return status; 240 } 241 242 status = FxValidateUnicodeString(pFxDriverGlobals, KeyName); 243 if (!NT_SUCCESS(status)) { 244 return status; 245 } 246 247 pKey = new (pFxDriverGlobals, KeyAttributes) FxRegKey(pFxDriverGlobals); 248 249 if (pKey == NULL) { 250 status = STATUS_INSUFFICIENT_RESOURCES; 251 DoTraceLevelMessage( 252 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 253 "Could not allocate memory for WDFKEY, %!STATUS!", status); 254 255 return status; 256 } 257 258 status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle); 259 260 if (NT_SUCCESS(status)) { 261 status = pKey->Create(parentHandle, 262 KeyName, 263 DesiredAccess, 264 CreateOptions, 265 CreateDisposition); 266 267 if (NT_SUCCESS(status)) { 268 *Key = keyHandle; 269 } 270 else { 271 DoTraceLevelMessage( 272 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 273 "Registry key creation failed, %!STATUS!", status); 274 } 275 } 276 277 if (!NT_SUCCESS(status)) { 278 pKey->DeleteFromFailedCreate(); 279 pKey = NULL; 280 } 281 282 return status; 283 } 284 285 __drv_maxIRQL(PASSIVE_LEVEL) 286 VOID 287 STDCALL 288 WDFEXPORT(WdfRegistryClose)( 289 __in 290 PWDF_DRIVER_GLOBALS DriverGlobals, 291 __in 292 WDFKEY Key 293 ) 294 { 295 DDI_ENTRY(); 296 297 PFX_DRIVER_GLOBALS pFxDriverGlobals; 298 FxRegKey* pKey; 299 NTSTATUS status; 300 301 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 302 Key, 303 FX_TYPE_REG_KEY, 304 (PVOID*) &pKey, 305 &pFxDriverGlobals); 306 307 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 308 if (!NT_SUCCESS(status)) { 309 FxVerifierDbgBreakPoint(pFxDriverGlobals); 310 return; 311 } 312 313 pKey->Close(); 314 315 pKey->DeleteObject(); 316 } 317 318 __drv_maxIRQL(PASSIVE_LEVEL) 319 HANDLE 320 STDCALL 321 WDFEXPORT(WdfRegistryWdmGetHandle)( 322 __in 323 PWDF_DRIVER_GLOBALS DriverGlobals, 324 __in 325 WDFKEY Key 326 ) 327 { 328 DDI_ENTRY(); 329 330 FxRegKey* pKey; 331 332 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 333 Key, 334 FX_TYPE_REG_KEY, 335 (PVOID*) &pKey); 336 337 return pKey->GetHandle(); 338 } 339 340 _Must_inspect_result_ 341 __drv_maxIRQL(PASSIVE_LEVEL) 342 NTSTATUS 343 STDCALL 344 WDFEXPORT(WdfRegistryRemoveKey)( 345 __in 346 PWDF_DRIVER_GLOBALS DriverGlobals, 347 __in 348 WDFKEY Key 349 ) 350 { 351 DDI_ENTRY(); 352 353 PFX_DRIVER_GLOBALS pFxDriverGlobals; 354 FxRegKey* pKey; 355 NTSTATUS status; 356 357 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 358 Key, 359 FX_TYPE_REG_KEY, 360 (PVOID*) &pKey, 361 &pFxDriverGlobals); 362 363 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 364 if (!NT_SUCCESS(status)) { 365 return status; 366 } 367 368 status = Mx::MxDeleteKey(pKey->GetHandle()); 369 370 if (NT_SUCCESS(status)) { 371 // 372 // pKey->GetHandle() is now useless, delete the Fx object 373 // 374 pKey->DeleteObject(); 375 } 376 377 return status; 378 } 379 380 _Must_inspect_result_ 381 __drv_maxIRQL(PASSIVE_LEVEL) 382 NTSTATUS 383 STDCALL 384 WDFEXPORT(WdfRegistryRemoveValue)( 385 __in 386 PWDF_DRIVER_GLOBALS DriverGlobals, 387 __in 388 WDFKEY Key, 389 __in 390 PCUNICODE_STRING ValueName 391 ) 392 { 393 DDI_ENTRY(); 394 395 PFX_DRIVER_GLOBALS pFxDriverGlobals; 396 FxRegKey* pKey; 397 NTSTATUS status; 398 399 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 400 Key, 401 FX_TYPE_REG_KEY, 402 (PVOID*) &pKey, 403 &pFxDriverGlobals); 404 405 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 406 if (!NT_SUCCESS(status)) { 407 return status; 408 } 409 410 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 411 if (!NT_SUCCESS(status)) { 412 return status; 413 } 414 415 FxPointerNotNull(pFxDriverGlobals, ValueName); 416 417 status = ZwDeleteValueKey(pKey->GetHandle(), (PUNICODE_STRING) ValueName); 418 419 return status; 420 } 421 422 _Must_inspect_result_ 423 __drv_maxIRQL(PASSIVE_LEVEL) 424 NTSTATUS 425 STDCALL 426 WDFEXPORT(WdfRegistryQueryValue)( 427 __in 428 PWDF_DRIVER_GLOBALS DriverGlobals, 429 __in 430 WDFKEY Key, 431 __in 432 PCUNICODE_STRING ValueName, 433 __in 434 ULONG ValueLength, 435 __out_bcount_opt( ValueLength) 436 PVOID Value, 437 __out_opt 438 PULONG ValueLengthQueried, 439 __out_opt 440 PULONG ValueType 441 ) 442 { 443 DDI_ENTRY(); 444 445 PFX_DRIVER_GLOBALS pFxDriverGlobals; 446 FxRegKey* pKey; 447 NTSTATUS status; 448 449 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 450 Key, 451 FX_TYPE_REG_KEY, 452 (PVOID*) &pKey, 453 &pFxDriverGlobals); 454 455 FxPointerNotNull(pFxDriverGlobals, ValueName); 456 457 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 458 if (!NT_SUCCESS(status)) { 459 return status; 460 } 461 462 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 463 if (!NT_SUCCESS(status)) { 464 return status; 465 } 466 467 status = FxRegKey::_QueryValue(pFxDriverGlobals, 468 pKey->GetHandle(), 469 ValueName, 470 ValueLength, 471 Value, 472 ValueLengthQueried, 473 ValueType); 474 if (!NT_SUCCESS(status)) { 475 UCHAR traceLevel = TRACE_LEVEL_ERROR; 476 477 // 478 // Label message as Verbose if this is the known pattern of 479 // passing a 0-length NULL buffer to query the required buffer size. 480 // 481 if (status == STATUS_BUFFER_OVERFLOW && Value == NULL && ValueLength == 0) { 482 traceLevel = TRACE_LEVEL_VERBOSE; 483 } 484 485 DoTraceLevelMessage(pFxDriverGlobals, traceLevel, TRACINGERROR, 486 "WDFKEY %p QueryValue failed, %!STATUS!", 487 Key, status); 488 } 489 490 return status; 491 } 492 493 _Must_inspect_result_ 494 __drv_maxIRQL(PASSIVE_LEVEL) 495 NTSTATUS 496 STDCALL 497 WDFEXPORT(WdfRegistryQueryMemory)( 498 __in 499 PWDF_DRIVER_GLOBALS DriverGlobals, 500 __in 501 WDFKEY Key, 502 __in 503 PCUNICODE_STRING ValueName, 504 __in 505 __drv_strictTypeMatch( 1) 506 POOL_TYPE PoolType, 507 __in_opt 508 PWDF_OBJECT_ATTRIBUTES MemoryAttributes, 509 __out 510 WDFMEMORY* Memory, 511 __out_opt 512 PULONG ValueType 513 ) 514 { 515 DDI_ENTRY(); 516 517 FxRegKey* pKey; 518 PFX_DRIVER_GLOBALS pFxDriverGlobals; 519 NTSTATUS status; 520 ULONG dataLength; 521 PVOID dataBuffer; 522 523 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 524 Key, 525 FX_TYPE_REG_KEY, 526 (PVOID*) &pKey, 527 &pFxDriverGlobals); 528 529 FxPointerNotNull(pFxDriverGlobals, ValueName); 530 FxPointerNotNull(pFxDriverGlobals, Memory); 531 532 *Memory = NULL; 533 534 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 535 if (!NT_SUCCESS(status)) { 536 return status; 537 } 538 539 FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag); 540 541 status = FxValidateObjectAttributes(pFxDriverGlobals, MemoryAttributes); 542 if (!NT_SUCCESS(status)) { 543 return status; 544 } 545 546 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 547 if (!NT_SUCCESS(status)) { 548 return status; 549 } 550 551 // 552 // Query the buffer length required. 553 // 554 status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, NULL); 555 if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) { 556 return status; 557 } 558 559 dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength); 560 if (dataBuffer == NULL) { 561 status = STATUS_INSUFFICIENT_RESOURCES; 562 563 DoTraceLevelMessage( 564 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 565 "WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, %!STATUS!", 566 Key, status); 567 568 return status; 569 } 570 571 status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, ValueType); 572 if (NT_SUCCESS(status)) { 573 FxMemoryObject* pObject; 574 575 status = FxMemoryObject::_Create(pFxDriverGlobals, 576 MemoryAttributes, 577 PoolType, 578 pFxDriverGlobals->Tag, 579 dataLength, 580 &pObject); 581 582 if (NT_SUCCESS(status)) { 583 status = pObject->Commit(MemoryAttributes, (WDFOBJECT*) Memory); 584 585 if (NT_SUCCESS(status)) { 586 RtlCopyMemory(pObject->GetBuffer(), 587 dataBuffer, 588 dataLength); 589 } 590 else { 591 pObject->DeleteFromFailedCreate(); 592 } 593 } 594 else { 595 DoTraceLevelMessage( 596 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 597 "WDFKEY %p WDFMEMORY object create failed, %!STATUS!", 598 Key, status); 599 } 600 } 601 else { 602 DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 603 "WDFKEY %p QueryPartial failed, %!STATUS!", 604 Key, status); 605 } 606 607 FxPoolFree(dataBuffer); 608 609 return status; 610 } 611 612 _Must_inspect_result_ 613 __drv_maxIRQL(PASSIVE_LEVEL) 614 NTSTATUS 615 STDCALL 616 WDFEXPORT(WdfRegistryQueryMultiString)( 617 __in 618 PWDF_DRIVER_GLOBALS DriverGlobals, 619 __in 620 WDFKEY Key, 621 __in 622 PCUNICODE_STRING ValueName, 623 __in_opt 624 PWDF_OBJECT_ATTRIBUTES StringsAttributes, 625 __in 626 WDFCOLLECTION Collection 627 ) 628 { 629 DDI_ENTRY(); 630 631 PFX_DRIVER_GLOBALS pFxDriverGlobals; 632 FxDeviceBase* pDeviceBase; 633 FxCollection* pCollection; 634 FxRegKey* pKey; 635 NTSTATUS status; 636 ULONG dataLength, type; 637 PVOID dataBuffer; 638 639 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 640 Key, 641 FX_TYPE_REG_KEY, 642 (PVOID*) &pKey, 643 &pFxDriverGlobals); 644 645 pDeviceBase = NULL; 646 647 FxPointerNotNull(pFxDriverGlobals, ValueName); 648 FxPointerNotNull(pFxDriverGlobals, Collection); 649 650 status = FxValidateObjectAttributes(pFxDriverGlobals, StringsAttributes); 651 if (!NT_SUCCESS(status)) { 652 return status; 653 } 654 655 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 656 if (!NT_SUCCESS(status)) { 657 return status; 658 } 659 660 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 661 if (!NT_SUCCESS(status)) { 662 return status; 663 } 664 665 FxObjectHandleGetPtr(pFxDriverGlobals, 666 Collection, 667 FX_TYPE_COLLECTION, 668 (PVOID*) &pCollection); 669 670 pDeviceBase = FxDeviceBase::_SearchForDevice(pFxDriverGlobals, 671 StringsAttributes); 672 673 status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, &type); 674 if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) { 675 DoTraceLevelMessage( 676 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 677 "WDFKEY %p QueryPartial failed: %!STATUS!", Key, status); 678 679 return status; 680 } 681 682 if (type != REG_MULTI_SZ) { 683 return STATUS_OBJECT_TYPE_MISMATCH; 684 } 685 686 dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength); 687 if (dataBuffer == NULL) { 688 status = STATUS_INSUFFICIENT_RESOURCES; 689 690 DoTraceLevelMessage( 691 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 692 "WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, %!STATUS!", 693 Key, status); 694 695 return status; 696 } 697 698 status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type); 699 if (NT_SUCCESS(status)) { 700 // 701 // Verify that the data from the registry is a valid multi-sz string. 702 // 703 status = FxRegKey::_VerifyMultiSzString(pFxDriverGlobals, 704 ValueName, 705 (PWCHAR) dataBuffer, 706 dataLength); 707 } 708 709 if (NT_SUCCESS(status)) { 710 ULONG initialCount; 711 PWCHAR pCur; 712 713 initialCount = pCollection->Count(); 714 pCur = (PWCHAR) dataBuffer; 715 716 while (*pCur != UNICODE_NULL) { 717 FxString* pString; 718 719 pString = new (pFxDriverGlobals, StringsAttributes) 720 FxString(pFxDriverGlobals); 721 722 if (pString != NULL) { 723 if (pDeviceBase != NULL) { 724 pString->SetDeviceBase(pDeviceBase); 725 } 726 727 status = pString->Assign(pCur); 728 729 if (NT_SUCCESS(status)) { 730 WDFOBJECT dummy; 731 732 status = pString->Commit(StringsAttributes, &dummy); 733 } 734 735 if (NT_SUCCESS(status)) { 736 if (pCollection->Add(pString) == FALSE) { 737 status = STATUS_INSUFFICIENT_RESOURCES; 738 739 DoTraceLevelMessage( 740 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 741 "WDFKEY %p, WDFCOLLECTION %p, collection add failed " 742 "%!STATUS!", Key, Collection, status); 743 } 744 } 745 746 if (!NT_SUCCESS(status)) { 747 // 748 // Delete the string we just created 749 // 750 pString->DeleteFromFailedCreate(); 751 } 752 else { 753 // 754 // NT_SUCCES(status) 755 // 756 // Either the caller is responsible for freeing the 757 // WDFSTRING or it has been parented to another object. 758 // 759 DO_NOTHING(); 760 } 761 } 762 else { 763 status = STATUS_INSUFFICIENT_RESOURCES; 764 } 765 766 if (!NT_SUCCESS(status)) { 767 DoTraceLevelMessage( 768 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 769 "WDFKEY %p: WDFSTRING creation failed: %!STATUS!", 770 Key, status); 771 break; 772 } 773 774 // 775 // Increment to the next string in the multi sz (length of string + 776 // 1 for the NULL) 777 // 778 pCur += wcslen(pCur) + 1; 779 } 780 781 if (!NT_SUCCESS(status)) { 782 // 783 // Clear out all the items we added to the collection 784 // 785 while (pCollection->Count() > initialCount) { 786 pCollection->Remove(initialCount); 787 } 788 } 789 } 790 791 FxPoolFree(dataBuffer); 792 793 return status; 794 } 795 796 _Must_inspect_result_ 797 __drv_maxIRQL(PASSIVE_LEVEL) 798 NTSTATUS 799 STDCALL 800 WDFEXPORT(WdfRegistryQueryUnicodeString)( 801 __in 802 PWDF_DRIVER_GLOBALS DriverGlobals, 803 __in 804 WDFKEY Key, 805 __in 806 PCUNICODE_STRING ValueName, 807 __out_opt 808 PUSHORT ValueByteLength, 809 __inout_opt 810 PUNICODE_STRING Value 811 ) 812 { 813 DDI_ENTRY(); 814 815 PFX_DRIVER_GLOBALS pFxDriverGlobals; 816 FxRegKey* pKey; 817 NTSTATUS status; 818 ULONG dataLength, type; 819 PVOID dataBuffer; 820 821 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 822 Key, 823 FX_TYPE_REG_KEY, 824 (PVOID*) &pKey, 825 &pFxDriverGlobals); 826 827 FxPointerNotNull(pFxDriverGlobals, ValueName); 828 829 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 830 if (!NT_SUCCESS(status)) { 831 return status; 832 } 833 834 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 835 if (!NT_SUCCESS(status)) { 836 return status; 837 } 838 839 if (Value != NULL) { 840 status = FxValidateUnicodeString(pFxDriverGlobals, Value); 841 if (!NT_SUCCESS(status)) { 842 return status; 843 } 844 } 845 846 if (Value == NULL) { 847 // 848 // Caller wants to know just the length 849 // 850 dataLength = 0; 851 dataBuffer = NULL; 852 } 853 else { 854 dataLength = Value->MaximumLength; 855 dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength); 856 857 if (dataBuffer == NULL) { 858 status = STATUS_INSUFFICIENT_RESOURCES; 859 860 DoTraceLevelMessage( 861 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 862 "WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, " 863 "%!STATUS!", Key, status); 864 865 return status; 866 } 867 } 868 869 status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type); 870 if (NT_SUCCESS(status) && 871 FxRegKey::_IsValidSzType(type) == FALSE) { 872 status = STATUS_OBJECT_TYPE_MISMATCH; 873 } 874 875 // 876 // Set ValueByteLength before doing the copy 877 // 878 if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { 879 // 880 // pPartial->DataLength is in bytes, convert to number of 881 // WCHARs 882 // 883 if (ValueByteLength != NULL) { 884 *ValueByteLength = (USHORT)dataLength ; 885 } 886 } 887 888 if (NT_SUCCESS(status) && Value != NULL) { 889 890 891 892 893 ASSERT(ValueByteLength == NULL || 894 *ValueByteLength >= dataLength); 895 896 // 897 // pPartial->DataLength cannot be greater than Value->MaximumLength 898 // based on the call to _ComputePartialSize above. So it is safe to 899 // copy the pPartial data buffer to the Value buffer. 900 // 901 __analysis_assume(dataLength <= Value->MaximumLength); 902 RtlCopyMemory(Value->Buffer, dataBuffer, dataLength); 903 904 //terminating null shouldn't be included in the Length 905 Value->Length = (USHORT)dataLength; 906 907 if (Value->Buffer[Value->Length/sizeof(WCHAR)-1] == UNICODE_NULL) { 908 Value->Length -= sizeof(WCHAR); 909 } 910 } 911 912 if (dataBuffer != NULL) { 913 FxPoolFree(dataBuffer); 914 } 915 916 return status; 917 } 918 919 _Must_inspect_result_ 920 __drv_maxIRQL(PASSIVE_LEVEL) 921 NTSTATUS 922 STDCALL 923 WDFEXPORT(WdfRegistryQueryString)( 924 __in 925 PWDF_DRIVER_GLOBALS DriverGlobals, 926 __in 927 WDFKEY Key, 928 __in 929 PCUNICODE_STRING ValueName, 930 __in 931 WDFSTRING String 932 ) 933 { 934 DDI_ENTRY(); 935 936 PFX_DRIVER_GLOBALS pFxDriverGlobals; 937 FxString* pString; 938 FxRegKey* pKey; 939 NTSTATUS status; 940 ULONG dataLength, type; 941 PVOID dataBuffer; 942 943 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 944 Key, 945 FX_TYPE_REG_KEY, 946 (PVOID*) &pKey, 947 &pFxDriverGlobals); 948 949 FxPointerNotNull(pFxDriverGlobals, ValueName); 950 FxPointerNotNull(pFxDriverGlobals, String); 951 952 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 953 if (!NT_SUCCESS(status)) { 954 return status; 955 } 956 957 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 958 if (!NT_SUCCESS(status)) { 959 return status; 960 } 961 962 FxObjectHandleGetPtr(pFxDriverGlobals, 963 String, 964 FX_TYPE_STRING, 965 (PVOID*) &pString); 966 967 status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, &type); 968 if (NT_SUCCESS(status) && 969 FxRegKey::_IsValidSzType(type) == FALSE) { 970 status = STATUS_OBJECT_TYPE_MISMATCH; 971 } 972 973 if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) { 974 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 975 "WDFKEY %p, QueryPartial failed, %!STATUS!", 976 Key, status); 977 return status; 978 } 979 980 dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength); 981 if (dataBuffer == NULL) { 982 status = STATUS_INSUFFICIENT_RESOURCES; 983 984 DoTraceLevelMessage( 985 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 986 "WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, " 987 "%!STATUS!", Key, status); 988 989 return status; 990 } 991 992 status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type); 993 if (NT_SUCCESS(status) && 994 FxRegKey::_IsValidSzType(type) == FALSE) { 995 status = STATUS_OBJECT_TYPE_MISMATCH; 996 } 997 998 if (NT_SUCCESS(status)) { 999 if (dataLength <= USHORT_MAX) { 1000 UNICODE_STRING tmp; 1001 1002 if (dataLength == 0x0) { 1003 // 1004 // Empty string 1005 // 1006 tmp.Buffer = L""; 1007 tmp.Length = 0; 1008 tmp.MaximumLength = 0; 1009 } 1010 else { 1011 1012 // 1013 // The string we read may not be NULL terminated, so put it into a 1014 // UNICODE_STRING. If the final character is NULL, shorten the 1015 // length of the string so that it does not include for the NULL. 1016 // 1017 // If there are embedded NULLs in the string previous to the final 1018 // character, we leave them in place. 1019 // 1020 tmp.Buffer = (PWCHAR) dataBuffer; 1021 tmp.Length = (USHORT) dataLength; 1022 tmp.MaximumLength = tmp.Length; 1023 1024 if (tmp.Buffer[(tmp.Length/sizeof(WCHAR))-1] == UNICODE_NULL) { 1025 // 1026 // Do not include the UNICODE_NULL in the length 1027 // 1028 tmp.Length -= sizeof(WCHAR); 1029 } 1030 } 1031 1032 status = pString->Assign(&tmp); 1033 } 1034 else { 1035 status = STATUS_INVALID_BUFFER_SIZE; 1036 1037 DoTraceLevelMessage( 1038 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1039 "WDFKEY %p QueryPartial failed, Length %d > max %d, %!STATUS!", 1040 Key, dataLength, USHORT_MAX, status); 1041 } 1042 } 1043 else { 1044 DoTraceLevelMessage( 1045 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1046 "WDFKEY %p QueryPartial failed, Length %d, %!STATUS!", 1047 Key, dataLength, status); 1048 } 1049 1050 FxPoolFree(dataBuffer); 1051 1052 return status; 1053 } 1054 1055 _Must_inspect_result_ 1056 __drv_maxIRQL(PASSIVE_LEVEL) 1057 NTSTATUS 1058 STDCALL 1059 WDFEXPORT(WdfRegistryQueryULong)( 1060 __in 1061 PWDF_DRIVER_GLOBALS DriverGlobals, 1062 __in 1063 WDFKEY Key, 1064 __in 1065 PCUNICODE_STRING ValueName, 1066 __out 1067 PULONG Value 1068 ) 1069 { 1070 DDI_ENTRY(); 1071 1072 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1073 FxRegKey* pKey; 1074 NTSTATUS status; 1075 1076 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1077 Key, 1078 FX_TYPE_REG_KEY, 1079 (PVOID*) &pKey, 1080 &pFxDriverGlobals); 1081 1082 FxPointerNotNull(pFxDriverGlobals, ValueName); 1083 FxPointerNotNull(pFxDriverGlobals, Value); 1084 1085 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1086 if (!NT_SUCCESS(status)) { 1087 return status; 1088 } 1089 1090 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 1091 if (!NT_SUCCESS(status)) { 1092 return status; 1093 } 1094 1095 status = FxRegKey::_QueryULong(pKey->GetHandle(), ValueName, Value); 1096 1097 if (!NT_SUCCESS(status)) { 1098 DoTraceLevelMessage( 1099 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1100 "WDFKEY %p, QueryULong, %!STATUS!", Key, status); 1101 } 1102 1103 return status; 1104 } 1105 1106 1107 _Must_inspect_result_ 1108 __drv_maxIRQL(PASSIVE_LEVEL) 1109 NTSTATUS 1110 STDCALL 1111 WDFEXPORT(WdfRegistryAssignValue)( 1112 __in 1113 PWDF_DRIVER_GLOBALS DriverGlobals, 1114 __in 1115 WDFKEY Key, 1116 __in 1117 PCUNICODE_STRING ValueName, 1118 __in 1119 ULONG ValueType, 1120 __in 1121 ULONG ValueLength, 1122 __in_ecount( ValueLength) 1123 PVOID Value 1124 ) 1125 { 1126 DDI_ENTRY(); 1127 1128 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1129 FxRegKey* pKey; 1130 NTSTATUS status; 1131 1132 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1133 Key, 1134 FX_TYPE_REG_KEY, 1135 (PVOID*) &pKey, 1136 &pFxDriverGlobals); 1137 1138 FxPointerNotNull(pFxDriverGlobals, ValueName); 1139 1140 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1141 if (!NT_SUCCESS(status)) { 1142 return status; 1143 } 1144 1145 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 1146 if (!NT_SUCCESS(status)) { 1147 return status; 1148 } 1149 1150 status = pKey->SetValue(ValueName, ValueType, Value, ValueLength); 1151 1152 if (!NT_SUCCESS(status)) { 1153 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1154 "WDFKEY %p SetValue, %!STATUS!", Key, status); 1155 } 1156 1157 return status; 1158 } 1159 1160 1161 _Must_inspect_result_ 1162 __drv_maxIRQL(PASSIVE_LEVEL) 1163 NTSTATUS 1164 STDCALL 1165 WDFEXPORT(WdfRegistryAssignMemory)( 1166 __in 1167 PWDF_DRIVER_GLOBALS DriverGlobals, 1168 __in 1169 WDFKEY Key, 1170 __in 1171 PCUNICODE_STRING ValueName, 1172 __in 1173 ULONG ValueType, 1174 __in 1175 WDFMEMORY Memory, 1176 __in_opt 1177 PWDFMEMORY_OFFSET MemoryOffsets 1178 ) 1179 { 1180 DDI_ENTRY(); 1181 1182 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1183 IFxMemory* pMemory; 1184 FxRegKey* pKey; 1185 PVOID pBuffer; 1186 ULONG length; 1187 NTSTATUS status; 1188 1189 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1190 Key, 1191 FX_TYPE_REG_KEY, 1192 (PVOID*) &pKey, 1193 &pFxDriverGlobals); 1194 1195 FxPointerNotNull(pFxDriverGlobals, ValueName); 1196 FxPointerNotNull(pFxDriverGlobals, Memory); 1197 1198 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1199 if (!NT_SUCCESS(status)) { 1200 return status; 1201 } 1202 1203 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 1204 if (!NT_SUCCESS(status)) { 1205 return status; 1206 } 1207 1208 FxObjectHandleGetPtr(pFxDriverGlobals, 1209 Memory, 1210 IFX_TYPE_MEMORY, 1211 (PVOID*) &pMemory); 1212 1213 pBuffer = pMemory->GetBuffer(); 1214 length = (ULONG) pMemory->GetBufferSize(); 1215 1216 if (MemoryOffsets != NULL) { 1217 status = pMemory->ValidateMemoryOffsets(MemoryOffsets); 1218 1219 if (!NT_SUCCESS(status)) { 1220 DoTraceLevelMessage( 1221 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1222 "WDFKEY %p, WDFMEMORY %p Offsets overflowed, %!STATUS!", 1223 Key, Memory, status); 1224 1225 return status; 1226 } 1227 1228 if (MemoryOffsets->BufferLength > 0) { 1229 status = RtlSizeTToULong(MemoryOffsets->BufferLength, &length); 1230 1231 if (!NT_SUCCESS(status)) { 1232 DoTraceLevelMessage( 1233 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1234 "WDFKEY %p, WDFMEMORY %p BufferLength in Offsets truncated, " 1235 "%!STATUS!", Key, Memory, status); 1236 1237 return status; 1238 } 1239 } 1240 1241 pBuffer = WDF_PTR_ADD_OFFSET(pBuffer, MemoryOffsets->BufferOffset); 1242 } 1243 1244 status = pKey->SetValue(ValueName, ValueType, pBuffer, length); 1245 1246 if (!NT_SUCCESS(status)) { 1247 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1248 "WDFKEY handle %p SetValue, %!STATUS!", Key, status); 1249 } 1250 1251 return status; 1252 } 1253 1254 _Must_inspect_result_ 1255 __drv_maxIRQL(PASSIVE_LEVEL) 1256 NTSTATUS 1257 STDCALL 1258 WDFEXPORT(WdfRegistryAssignULong)( 1259 __in 1260 PWDF_DRIVER_GLOBALS DriverGlobals, 1261 __in 1262 WDFKEY Key, 1263 __in 1264 PCUNICODE_STRING ValueName, 1265 __in 1266 ULONG Value 1267 ) 1268 { 1269 DDI_ENTRY(); 1270 1271 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1272 FxRegKey* pKey; 1273 NTSTATUS status; 1274 1275 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1276 Key, 1277 FX_TYPE_REG_KEY, 1278 (PVOID*) &pKey, 1279 &pFxDriverGlobals); 1280 1281 FxPointerNotNull(pFxDriverGlobals, ValueName); 1282 1283 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1284 if (!NT_SUCCESS(status)) { 1285 return status; 1286 } 1287 1288 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 1289 if (!NT_SUCCESS(status)) { 1290 return status; 1291 } 1292 1293 status = pKey->SetValue(ValueName, REG_DWORD, &Value, sizeof(Value)); 1294 1295 if (!NT_SUCCESS(status)) { 1296 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1297 "WDFKEY %p SetValue, %!STATUS!", 1298 Key, status); 1299 } 1300 1301 return status; 1302 } 1303 1304 _Must_inspect_result_ 1305 __drv_maxIRQL(PASSIVE_LEVEL) 1306 NTSTATUS 1307 STDCALL 1308 WDFEXPORT(WdfRegistryAssignUnicodeString)( 1309 __in 1310 PWDF_DRIVER_GLOBALS DriverGlobals, 1311 __in 1312 WDFKEY Key, 1313 __in 1314 PCUNICODE_STRING ValueName, 1315 __in 1316 PCUNICODE_STRING Value 1317 ) 1318 { 1319 DDI_ENTRY(); 1320 1321 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1322 FxRegKey* pKey; 1323 NTSTATUS status; 1324 PWCHAR tempValueBuf; 1325 ULONG length; 1326 1327 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1328 Key, 1329 FX_TYPE_REG_KEY, 1330 (PVOID*) &pKey, 1331 &pFxDriverGlobals); 1332 1333 FxPointerNotNull(pFxDriverGlobals, ValueName); 1334 FxPointerNotNull(pFxDriverGlobals, Value); 1335 1336 tempValueBuf = NULL; 1337 1338 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1339 if (!NT_SUCCESS(status)) { 1340 return status; 1341 } 1342 1343 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 1344 if (!NT_SUCCESS(status)) { 1345 return status; 1346 } 1347 1348 status = FxValidateUnicodeString(pFxDriverGlobals, Value); 1349 if (!NT_SUCCESS(status)) { 1350 return status; 1351 } 1352 1353 length = Value->Length + sizeof(UNICODE_NULL); 1354 1355 // 1356 // Buffer must be NULL terminated and Length of the buffer must also include the NULL 1357 // Allocate a temporary buffer and NULL terminate it. 1358 // 1359 tempValueBuf = (PWCHAR) FxPoolAllocate(pFxDriverGlobals, PagedPool, length); 1360 1361 if (tempValueBuf == NULL) { 1362 status = STATUS_INSUFFICIENT_RESOURCES; 1363 1364 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1365 "WDFKEY %p allocate temporary buffer failed, " 1366 "%!STATUS!", Key, status); 1367 1368 return status; 1369 } 1370 1371 // 1372 // Copy over the string from the callers buffer and make sure it is 1373 // NULL terminated. 1374 // 1375 RtlCopyMemory(tempValueBuf, Value->Buffer, Value->Length); 1376 tempValueBuf[Value->Length/sizeof(WCHAR)] = UNICODE_NULL; 1377 1378 status = pKey->SetValue(ValueName, REG_SZ, tempValueBuf, length); 1379 1380 FxPoolFree(tempValueBuf); 1381 1382 if (!NT_SUCCESS(status)) { 1383 DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1384 "WDFKEY %p set value failed, %!STATUS!", 1385 Key, status); 1386 } 1387 1388 return status; 1389 } 1390 1391 _Must_inspect_result_ 1392 __drv_maxIRQL(PASSIVE_LEVEL) 1393 NTSTATUS 1394 STDCALL 1395 WDFEXPORT(WdfRegistryAssignString)( 1396 __in 1397 PWDF_DRIVER_GLOBALS DriverGlobals, 1398 __in 1399 WDFKEY Key, 1400 __in 1401 PCUNICODE_STRING ValueName, 1402 __in 1403 WDFSTRING String 1404 ) 1405 { 1406 DDI_ENTRY(); 1407 1408 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1409 FxString* pString; 1410 FxRegKey* pKey; 1411 NTSTATUS status; 1412 1413 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1414 Key, 1415 FX_TYPE_REG_KEY, 1416 (PVOID*) &pKey, 1417 &pFxDriverGlobals); 1418 1419 FxPointerNotNull(pFxDriverGlobals, ValueName); 1420 FxPointerNotNull(pFxDriverGlobals, String); 1421 1422 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1423 if (!NT_SUCCESS(status)) { 1424 return status; 1425 } 1426 1427 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 1428 if (!NT_SUCCESS(status)) { 1429 return status; 1430 } 1431 1432 FxObjectHandleGetPtr(pFxDriverGlobals, 1433 String, 1434 FX_TYPE_STRING, 1435 (PVOID*) &pString); 1436 1437 status = pKey->SetValue(ValueName, 1438 REG_SZ, 1439 pString->Buffer(), 1440 pString->ByteLength(TRUE)); 1441 1442 if (!NT_SUCCESS(status)) { 1443 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1444 "WDFKEY handle %p SetValue, %!STATUS!", 1445 Key, status); 1446 } 1447 1448 return status; 1449 } 1450 1451 _Must_inspect_result_ 1452 __drv_maxIRQL(PASSIVE_LEVEL) 1453 NTSTATUS 1454 STDCALL 1455 WDFEXPORT(WdfRegistryAssignMultiString)( 1456 __in 1457 PWDF_DRIVER_GLOBALS DriverGlobals, 1458 __in 1459 WDFKEY Key, 1460 __in 1461 PCUNICODE_STRING ValueName, 1462 __in 1463 WDFCOLLECTION StringsCollection 1464 ) 1465 { 1466 DDI_ENTRY(); 1467 1468 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1469 FxCollection* pCollection; 1470 FxRegKey* pKey; 1471 PWCHAR pValue; 1472 NTSTATUS status; 1473 ULONG length; 1474 BOOLEAN valid; 1475 1476 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1477 Key, 1478 FX_TYPE_REG_KEY, 1479 (PVOID*) &pKey, 1480 &pFxDriverGlobals); 1481 1482 FxPointerNotNull(pFxDriverGlobals, ValueName); 1483 FxPointerNotNull(pFxDriverGlobals, StringsCollection); 1484 1485 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1486 if (!NT_SUCCESS(status)) { 1487 return status; 1488 } 1489 1490 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName); 1491 if (!NT_SUCCESS(status)) { 1492 return status; 1493 } 1494 1495 FxObjectHandleGetPtr(pFxDriverGlobals, 1496 StringsCollection, 1497 FX_TYPE_COLLECTION, 1498 (PVOID *) &pCollection); 1499 1500 valid = FALSE; 1501 1502 status = RtlSizeTToULong( 1503 FxCalculateTotalStringSize(pCollection, TRUE, &valid), 1504 &length); 1505 1506 if (!NT_SUCCESS(status)) { 1507 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1508 "WDFCOLLECTION %p, collection too large to fit into " 1509 "a ULONG, %!STATUS!", StringsCollection, status); 1510 return status; 1511 } 1512 1513 if (valid == FALSE) { 1514 status = STATUS_INVALID_PARAMETER; 1515 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1516 "WDFKEY %p, WDFCOLLECTION %p contains " 1517 "non string objects, %!STATUS!", 1518 Key, StringsCollection, status); 1519 return status; 1520 } 1521 1522 pValue = (PWCHAR) FxPoolAllocate(pFxDriverGlobals, PagedPool, length); 1523 1524 if (pValue == NULL) { 1525 status = STATUS_INSUFFICIENT_RESOURCES; 1526 1527 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1528 "WDFKEY %p allocate for query buffer failed, " 1529 "%!STATUS!", Key, status); 1530 1531 return status; 1532 } 1533 1534 FxCopyMultiSz(pValue, pCollection); 1535 1536 status = pKey->SetValue(ValueName, REG_MULTI_SZ, pValue, length); 1537 1538 if (!NT_SUCCESS(status)) { 1539 DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, 1540 "WDFKEY %p SetValue, %!STATUS!", 1541 Key, status); 1542 } 1543 1544 FxPoolFree(pValue); 1545 1546 return status; 1547 } 1548 1549 } // extern "C" 1550