Reactos
at master 778 lines 22 kB view raw
1/*++ 2 3Copyright (c) Microsoft Corporation 4 5Module Name: 6 7 Version.cpp 8 9Abstract: 10 11 This module forms a loadable library from the WDF core libs 12 13Revision History: 14 15--*/ 16 17#include <stdarg.h> 18#include <stddef.h> 19#include <stdio.h> 20#include <string.h> 21#include <ntverp.h> 22 23extern "C" { 24#include <ntddk.h> 25#include <ntstrsafe.h> 26} 27 28#define FX_DYNAMICS_GENERATE_TABLE 1 29 30#include "fx.hpp" 31 32#include <fxldr.h> 33#include "fxbugcheck.h" 34// #include "wdfversionlog.h" 35#include "reactos_special.h" 36 37#define DRIVER_OBJECT_EXTENSION_IDENTIFIER DriverEntry 38#define DRIVER_PARAMETERS L"Parameters" 39#define REGISTRY_KMDF_MAJOR_VERSION L"MajorVersion" 40#define REGISTRY_KMDF_MINOR_VERSION L"MinorVersion" 41#define REGISTRY_KMDF_BUILD_NUMBER L"BuildNumber" 42 43//----------------------------------------------------------------------------- 44// These header files are referenced in order to make internal structures 45// available in public symbols. Various WDFKD debug commands use these 46// internal structures to provide information about WDF. 47//----------------------------------------------------------------------------- 48#include "fxifr.h" 49 50extern "C" { 51 52// 53// This is the collection of all structure/types to be make public. 54// This union forces the structure type-info into the PDB file. 55// 56union { 57 58 WDF_IFR_HEADER * typeWDF_IFR_HEADER; 59 WDF_IFR_RECORD * typeWDF_IFR_RECORD; 60 WDF_IFR_OFFSET * typeWDF_IFR_OFFSET; 61 WDF_BIND_INFO * typeWDF_BIND_INFO; 62 WDF_OBJECT_CONTEXT_TYPE_INFO * typeWDF_OBJECT_CONTEXT_TYPE_INFO; 63 WDF_POWER_ROUTINE_TIMED_OUT_DATA * typeWDF_POWER_ROUTINE_TIMED_OUT_DATA; 64 WDF_BUGCHECK_CODES * typeWDF_BUGCHECK_CODES; 65 WDF_REQUEST_FATAL_ERROR_CODES * typeWDF_REQUEST_FATAL_ERROR_CODES; 66 FX_OBJECT_INFO * typeFX_OBJECT_INFO; 67 FX_POOL_HEADER * typeFX_POOL_HEADER; 68 FX_POOL * typeFX_POOL; 69 FxObject * typeFxObject; 70 FxContextHeader * typeFxContextHeader; 71 FX_DUMP_DRIVER_INFO_ENTRY * typeFX_DUMP_DRIVER_INFO_ENTRY; 72 FxTargetSubmitSyncParams * typeFxTargetSubmitSyncParams; 73 74} uAllPublicTypes; 75 76} // extern "C" end 77 78//----------------------------------------- ------------------------------------ 79 80extern "C" { 81 82#include "fxdynamics.h" 83 84#include "fxlibrarycommon.h" 85 86#ifdef __REACTOS__ 87#define KMDF_DEFAULT_NAME "Wdf" \ 88 LITERAL(__WDF_MAJOR_VERSION_STRING) \ 89 "000" //minor version 90#else 91#define KMDF_DEFAULT_NAME "Wdf" ## \ 92 LITERAL(__WDF_MAJOR_VERSION_STRING) ## \ 93 "000" //minor version 94#endif 95 96//----------------------------------------------------------------------------- 97// local prototype definitions 98//----------------------------------------------------------------------------- 99extern "C" 100DRIVER_UNLOAD DriverUnload; 101 102extern "C" 103DRIVER_INITIALIZE DriverEntry; 104 105extern "C" 106__drv_dispatchType(IRP_MJ_CREATE) 107__drv_dispatchType(IRP_MJ_CLEANUP) 108__drv_dispatchType(IRP_MJ_CLOSE) 109DRIVER_DISPATCH FxLibraryDispatch; 110 111RTL_OSVERSIONINFOW gOsVersion = { sizeof(RTL_OSVERSIONINFOW) }; 112 113ULONG WdfLdrDbgPrintOn = 0; 114 115PCHAR WdfLdrType = KMDF_DEFAULT_NAME; 116 117} // extern "C" 118 119 120//----------------------------------------------------------------------------- 121// 122//----------------------------------------------------------------------------- 123extern "C" 124_Must_inspect_result_ 125NTSTATUS 126NTAPI 127WDF_LIBRARY_COMMISSION( 128 VOID 129 ); 130 131extern "C" 132_Must_inspect_result_ 133NTSTATUS 134NTAPI 135WDF_LIBRARY_DECOMMISSION( 136 VOID 137 ); 138 139extern "C" 140_Must_inspect_result_ 141NTSTATUS 142NTAPI 143WDF_LIBRARY_REGISTER_CLIENT( 144 __inout PWDF_BIND_INFO Info, 145 __deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals, 146 __deref_inout PVOID * Context 147 ); 148 149extern "C" 150_Must_inspect_result_ 151NTSTATUS 152NTAPI 153WDF_LIBRARY_UNREGISTER_CLIENT( 154 __in PWDF_BIND_INFO Info, 155 __in PWDF_DRIVER_GLOBALS WdfDriverGlobals 156 ); 157 158extern "C" 159VOID 160FxLibraryDeleteDevice( 161 VOID 162 ); 163 164VOID 165FxLibraryCleanup( 166 VOID 167 ); 168 169VOID 170WdfWriteKmdfVersionToRegistry( 171 __in PDRIVER_OBJECT DriverObject, 172 __in PUNICODE_STRING RegistryPath 173 ); 174 175VOID 176WdfDeleteKmdfVersionFromRegistry( 177 __in PDRIVER_OBJECT DriverObject 178 ); 179 180typedef struct _DRV_EXTENSION { 181 UNICODE_STRING ParametersRegistryPath; 182} DRV_EXTENSION, *PDRV_EXTENSION; 183 184//----------------------------------------------------------------------------- 185// Library registeration information 186//----------------------------------------------------------------------------- 187extern "C" { 188#pragma prefast(suppress:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "kernel component."); 189WDF_LIBRARY_INFO WdfLibraryInfo = { 190 sizeof(WDF_LIBRARY_INFO), 191 (PFNLIBRARYCOMMISSION) WDF_LIBRARY_COMMISSION, 192 (PFNLIBRARYDECOMMISSION) WDF_LIBRARY_DECOMMISSION, 193 (PFNLIBRARYREGISTERCLIENT) WDF_LIBRARY_REGISTER_CLIENT, 194 (PFNLIBRARYUNREGISTERCLIENT) WDF_LIBRARY_UNREGISTER_CLIENT, 195 { __WDF_MAJOR_VERSION, __WDF_MINOR_VERSION, __WDF_BUILD_NUMBER } 196}; 197 198} // extern "C" end 199 200extern "C" 201NTSTATUS 202NTAPI 203FxLibraryDispatch ( 204 __in struct _DEVICE_OBJECT * DeviceObject, 205 __in PIRP Irp 206 ) 207{ 208 NTSTATUS status; 209 210 UNREFERENCED_PARAMETER(DeviceObject); 211 ASSERT(FxLibraryGlobals.LibraryDeviceObject == DeviceObject); 212 213 status = STATUS_INVALID_DEVICE_REQUEST; 214 215 switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction) { 216 case IRP_MJ_CREATE: 217 // 218 // To limit our exposure for this device object, only allow kernel mode 219 // creates. 220 // 221 if (Irp->RequestorMode == KernelMode) { 222 status = STATUS_SUCCESS; 223 } 224 break; 225 226 case IRP_MJ_CLEANUP: 227 case IRP_MJ_CLOSE: 228 // 229 // Since we allowed a create to succeed, succeed the cleanup and close 230 // 231 status = STATUS_SUCCESS; 232 break; 233 } 234 235 Irp->IoStatus.Status = status; 236 Irp->IoStatus.Information = 0x0; 237 IoCompleteRequest(Irp, IO_NO_INCREMENT); 238 239 return status; 240} 241 242//----------------------------------------------------------------------------- 243// 244//----------------------------------------------------------------------------- 245 246#define KMDF_DEVICE_NAME L"\\Device\\KMDF" 247 248_Must_inspect_result_ 249NTSTATUS 250FxLibraryCreateDevice( 251 __in PUNICODE_STRING DeviceName 252 ) 253{ 254 NTSTATUS status; 255 ULONG i; 256 257 i = 0; 258 259 // 260 // Repeatedly try to create a named device object until we run out of buffer 261 // space or we succeed. 262 // 263 do { 264 status = RtlUnicodeStringPrintf(DeviceName, L"%s%d", KMDF_DEVICE_NAME, i++); 265 if (!NT_SUCCESS(status)) { 266 return status; 267 } 268 269 // 270 // Create a device with no device extension 271 // 272 status = IoCreateDevice( 273 FxLibraryGlobals.DriverObject, 274 0, 275 DeviceName, 276 FILE_DEVICE_UNKNOWN, 277 0, 278 FALSE, 279 &FxLibraryGlobals.LibraryDeviceObject 280 ); 281 } while (STATUS_OBJECT_NAME_COLLISION == status); 282 283 if (NT_SUCCESS(status)) { 284 // 285 // Clear the initializing bit now because the loader will attempt to 286 // open the device before we return from DriverEntry 287 // 288 ASSERT(FxLibraryGlobals.LibraryDeviceObject != NULL); 289 FxLibraryGlobals.LibraryDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 290 } 291 292 return status; 293} 294 295extern "C" 296VOID 297FxLibraryDeleteDevice( 298 VOID 299 ) 300{ 301 FxLibraryCleanup(); 302} 303 304VOID 305FxLibraryCleanup( 306 VOID 307 ) 308{ 309 if (FxLibraryGlobals.LibraryDeviceObject != NULL) { 310 IoDeleteDevice(FxLibraryGlobals.LibraryDeviceObject); 311 FxLibraryGlobals.LibraryDeviceObject = NULL; 312 } 313} 314 315extern "C" 316NTSTATUS 317NTAPI 318DriverEntry( 319 __in PDRIVER_OBJECT DriverObject, 320 __in PUNICODE_STRING RegistryPath 321 ) 322{ 323 UNICODE_STRING name; 324 UNICODE_STRING string; 325 NTSTATUS status; 326 327 // 328 // This creates a local buffer which is big enough to hold a copy of the 329 // constant string assigned to it. It does not point to the constant 330 // string. As such, it is a writeable buffer. 331 // 332 // NOTE: KMDF_DEVICE_NAME L"XXXX" creates a concatenated string of 333 // KMDF_DEVICE_NAME + L"XXXX". This is done to give us room for 334 // appending a number up to 4 digits long after KMDF_DEVICE_NAME if 335 // you want a null terminated string, 5 digits long if the string is 336 // not null terminated (as is the case for a UNICODE_STRING) 337 // 338 WCHAR buffer[] = KMDF_DEVICE_NAME L"XXXX"; 339 340 // 341 // Initialize global to make NonPagedPool be treated as NxPool on Win8 342 // and NonPagedPool on down-level 343 // 344#ifndef __REACTOS__ 345 ExInitializeDriverRuntime(DrvRtPoolNxOptIn); 346#endif 347 RtlInitUnicodeString(&string, WDF_REGISTRY_DBGPRINT_ON); 348 349 // 350 // Determine if debug prints are on. 351 // 352 (void) WdfLdrDiagnosticsValueByNameAsULONG(&string, &WdfLdrDbgPrintOn); 353 354 __Print(("DriverEntry\n")); 355 356 DriverObject->DriverUnload = DriverUnload; 357 358 FxLibraryGlobals.DriverObject = DriverObject; 359 360 DriverObject->MajorFunction[IRP_MJ_CREATE] = FxLibraryDispatch; 361 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FxLibraryDispatch; 362 DriverObject->MajorFunction[IRP_MJ_CLOSE] = FxLibraryDispatch; 363 364 RtlZeroMemory(&name, sizeof(name)); 365 name.Buffer = buffer; 366 name.Length = 0x0; 367 name.MaximumLength = sizeof(buffer); 368 369 // 370 // We use the string when we declare the buffer to get the right sized 371 // buffer. Now we want to make sure there are no contents before we 372 // use it to create a device object. 373 // 374 RtlZeroMemory(buffer, sizeof(buffer)); 375 376 status = FxLibraryCreateDevice(&name); 377 if (!NT_SUCCESS(status)) { 378 __Print(("ERROR: FxLibraryCreateDevice failed with Status 0x%x\n", status)); 379 return status; 380 } 381 382 // 383 // Register this library with WdfLdr 384 // 385 // NOTE: Once WdfRegisterLibrary returns NT_SUCCESS() we must return 386 // NT_SUCCESS from DriverEntry! 387 // 388 status = WdfRegisterLibrary( &WdfLibraryInfo, RegistryPath, &name ); 389 if (!NT_SUCCESS(status)) { 390 __Print(("ERROR: WdfRegisterLibrary failed with Status 0x%x\n", status)); 391 FxLibraryCleanup(); 392 return status; 393 } 394 395 // 396 // Write KMDF version to registry 397 // 398 WdfWriteKmdfVersionToRegistry(DriverObject, RegistryPath); 399 400 return STATUS_SUCCESS; 401} 402 403//----------------------------------------------------------------------------- 404// 405//----------------------------------------------------------------------------- 406extern "C" 407VOID 408NTAPI 409DriverUnload( 410 __in PDRIVER_OBJECT DriverObject 411 ) 412{ 413 __Print(("DriverUnload\n")); 414 415 // 416 // Delete KMDF version from registry before destroying the Driver Object 417 // 418 WdfDeleteKmdfVersionFromRegistry(DriverObject); 419 420 // 421 // Make sure everything is deleted. Since the driver is considered a legacy 422 // driver, it can be unloaded while there are still outstanding device objects. 423 // 424 FxLibraryCleanup(); 425} 426 427//----------------------------------------------------------------------------- 428// 429//----------------------------------------------------------------------------- 430extern "C" 431_Must_inspect_result_ 432NTSTATUS 433NTAPI 434WDF_LIBRARY_COMMISSION( 435 VOID 436 ) 437{ 438 return FxLibraryCommonCommission(); 439} 440 441//----------------------------------------------------------------------------- 442// 443//----------------------------------------------------------------------------- 444extern "C" 445_Must_inspect_result_ 446NTSTATUS 447NTAPI 448WDF_LIBRARY_DECOMMISSION( 449 VOID 450 ) 451{ 452 return FxLibraryCommonDecommission(); 453} 454 455#define EVTLOG_MESSAGE_SIZE 70 456#define RAW_DATA_SIZE 4 457 458extern "C" 459_Must_inspect_result_ 460NTSTATUS 461NTAPI 462WDF_LIBRARY_REGISTER_CLIENT( 463 __in PWDF_BIND_INFO Info, 464 __deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals, 465 __deref_inout PVOID * Context 466 ) 467{ 468 NTSTATUS status = STATUS_INVALID_PARAMETER; 469 PFX_DRIVER_GLOBALS pFxDriverGlobals; 470 WCHAR insertString[EVTLOG_MESSAGE_SIZE]; 471 ULONG rawData[RAW_DATA_SIZE]; 472 PCLIENT_INFO clientInfo = NULL; 473 474 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": enter\n")); 475 476 clientInfo = (PCLIENT_INFO)*Context; 477 *Context = NULL; 478 479 ASSERT(Info->Version.Major == WdfLibraryInfo.Version.Major); 480 481 // 482 // NOTE: If the currently loaded library < drivers minor version fail the load 483 // instead of binding to a lower minor version. The reason for that if there 484 // is a newer API or new contract change made the driver shouldn't be using older 485 // API than it was compiled with. 486 // 487 488 if (Info->Version.Minor > WdfLibraryInfo.Version.Minor) { 489 status = RtlStringCchPrintfW(insertString, 490 RTL_NUMBER_OF(insertString), 491 L"Driver Version: %d.%d Kmdf Lib. Version: %d.%d", 492 Info->Version.Major, 493 Info->Version.Minor, 494 WdfLibraryInfo.Version.Major, 495 WdfLibraryInfo.Version.Minor); 496 if (!NT_SUCCESS(status)) { 497 __Print(("ERROR: RtlStringCchPrintfW failed with Status 0x%x\n", status)); 498 return status; 499 } 500 rawData[0] = Info->Version.Major; 501 rawData[1] = Info->Version.Minor; 502 rawData[2] = WdfLibraryInfo.Version.Major; 503 rawData[3] = WdfLibraryInfo.Version.Minor; 504 505 LibraryLogEvent(FxLibraryGlobals.DriverObject, 506 WDFVER_MINOR_VERSION_NOT_SUPPORTED, 507 STATUS_OBJECT_TYPE_MISMATCH, 508 insertString, 509 rawData, 510 sizeof(rawData) ); 511 // 512 // this looks like the best status to return 513 // 514 return STATUS_OBJECT_TYPE_MISMATCH; 515 516 } 517 518 status = FxLibraryCommonRegisterClient(Info, 519 WdfDriverGlobals, 520 clientInfo); 521 522 if (NT_SUCCESS(status)) { 523 // 524 // The context will be a pointer to FX_DRIVER_GLOBALS 525 // 526 *Context = GetFxDriverGlobals(*WdfDriverGlobals); 527 528 // 529 // Set the WDF_BIND_INFO structure pointer in FxDriverGlobals 530 // 531 pFxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals); 532 pFxDriverGlobals->WdfBindInfo = Info; 533 } 534 535 return status; 536} 537 538 539//----------------------------------------------------------------------------- 540// 541//----------------------------------------------------------------------------- 542extern "C" 543_Must_inspect_result_ 544NTSTATUS 545NTAPI 546WDF_LIBRARY_UNREGISTER_CLIENT( 547 __in PWDF_BIND_INFO Info, 548 __in PWDF_DRIVER_GLOBALS WdfDriverGlobals 549 ) 550{ 551 return FxLibraryCommonUnregisterClient(Info, WdfDriverGlobals); 552} 553 554VOID 555WdfWriteKmdfVersionToRegistry( 556 __in PDRIVER_OBJECT DriverObject, 557 __in PUNICODE_STRING RegistryPath 558 ) 559{ 560 NTSTATUS status; 561 OBJECT_ATTRIBUTES objectAttributes; 562 HANDLE driverKey; 563 HANDLE parametersKey; 564 UNICODE_STRING valueName; 565 UNICODE_STRING parametersPath; 566 PDRV_EXTENSION driverExtension; 567 568 driverKey = NULL; 569 parametersKey = NULL; 570 driverExtension = NULL; 571 572 RtlInitUnicodeString(&parametersPath, DRIVER_PARAMETERS); 573 574 InitializeObjectAttributes(&objectAttributes, 575 RegistryPath, 576 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 577 NULL, 578 NULL); 579 580 status = ZwOpenKey(&driverKey, KEY_CREATE_SUB_KEY, &objectAttributes); 581 if (!NT_SUCCESS(status)) { 582 __Print(("WdfWriteKmdfVersionToRegistry: Failed to open HKLM\\%S\n", 583 RegistryPath->Buffer)); 584 goto out; 585 } 586 587 InitializeObjectAttributes(&objectAttributes, 588 &parametersPath, 589 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 590 driverKey, 591 NULL); 592 593 // 594 // Open or create key and get a handle 595 // 596 status = ZwCreateKey(&parametersKey, 597 KEY_SET_VALUE, 598 &objectAttributes, 599 0, 600 (PUNICODE_STRING) NULL, 601 REG_OPTION_VOLATILE, 602 NULL); 603 604 if (!NT_SUCCESS(status)) { 605 __Print(("WdfWriteKmdfVersionToRegistry: Failed to open HKLM\\%S\\%S\n", 606 RegistryPath->Buffer, parametersPath.Buffer)); 607 goto out; 608 } 609 610 // 611 // Set Major Version 612 // 613 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MAJOR_VERSION); 614 615 status = ZwSetValueKey(parametersKey, 616 &valueName, 617 0, 618 REG_DWORD, 619 &WdfLibraryInfo.Version.Major, 620 sizeof(WdfLibraryInfo.Version.Major)); 621 622 if (!NT_SUCCESS(status)) { 623 __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Major Version\n")); 624 goto out; 625 } 626 627 // 628 // Set Minor Version 629 // 630 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MINOR_VERSION); 631 632 status = ZwSetValueKey(parametersKey, 633 &valueName, 634 0, 635 REG_DWORD, 636 &WdfLibraryInfo.Version.Minor, 637 sizeof(WdfLibraryInfo.Version.Minor)); 638 639 if (!NT_SUCCESS(status)) { 640 __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Minor Version\n")); 641 goto out; 642 } 643 644 645 // 646 // Set Build Number 647 // 648 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_BUILD_NUMBER); 649 650 status = ZwSetValueKey(parametersKey, 651 &valueName, 652 0, 653 REG_DWORD, 654 &WdfLibraryInfo.Version.Build, 655 sizeof(WdfLibraryInfo.Version.Build)); 656 657 if (!NT_SUCCESS(status)) { 658 __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Build Number\n")); 659 goto out; 660 } 661 662 // 663 // Create a Driver Extension to store the registry path, where we write the 664 // version of the wdf01000.sys that's loaded in memory 665 // 666 status = IoAllocateDriverObjectExtension(DriverObject, 667 (PVOID) DRIVER_OBJECT_EXTENSION_IDENTIFIER, 668 sizeof(DRV_EXTENSION), 669 (PVOID *)&driverExtension); 670 671 if (!NT_SUCCESS(status) || driverExtension == NULL) { 672 goto out; 673 } 674 675 driverExtension->ParametersRegistryPath.Buffer = (PWCHAR) ExAllocatePoolWithTag( 676 PagedPool, 677 RegistryPath->MaximumLength, 678 FX_TAG); 679 if (driverExtension->ParametersRegistryPath.Buffer == NULL) { 680 goto out; 681 } 682 683 driverExtension->ParametersRegistryPath.MaximumLength = RegistryPath->MaximumLength; 684 RtlCopyUnicodeString(&(driverExtension->ParametersRegistryPath), RegistryPath); 685 686out: 687 if (driverKey != NULL) { 688 ZwClose(driverKey); 689 } 690 691 if (parametersKey != NULL) { 692 ZwClose(parametersKey); 693 } 694 695 return; 696} 697 698VOID 699WdfDeleteKmdfVersionFromRegistry( 700 __in PDRIVER_OBJECT DriverObject 701 ) 702{ 703 PUNICODE_STRING registryPath; 704 OBJECT_ATTRIBUTES objectAttributes; 705 HANDLE driverKey; 706 HANDLE parametersKey; 707 UNICODE_STRING valueName; 708 NTSTATUS status; 709 UNICODE_STRING parametersPath; 710 PDRV_EXTENSION driverExtension; 711 712 RtlInitUnicodeString(&parametersPath, DRIVER_PARAMETERS); 713 714 driverKey = NULL; 715 parametersKey = NULL; 716 717 driverExtension = (PDRV_EXTENSION)IoGetDriverObjectExtension(DriverObject, 718 (PVOID)DRIVER_OBJECT_EXTENSION_IDENTIFIER); 719 720 if (driverExtension == NULL || driverExtension->ParametersRegistryPath.Buffer == NULL) { 721 return; 722 } 723 724 registryPath = &driverExtension->ParametersRegistryPath; 725 726 InitializeObjectAttributes(&objectAttributes, 727 registryPath, 728 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 729 NULL, 730 NULL); 731 732 status = ZwOpenKey(&driverKey, KEY_SET_VALUE, &objectAttributes); 733 if (!NT_SUCCESS(status)) { 734 goto out; 735 } 736 737 InitializeObjectAttributes(&objectAttributes, 738 &parametersPath, 739 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 740 driverKey, 741 NULL); 742 // 743 // Open the key for deletion 744 // 745 status = ZwOpenKey(&parametersKey, 746 DELETE, 747 &objectAttributes); 748 749 if (!NT_SUCCESS(status)) { 750 goto out; 751 } 752 753 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MAJOR_VERSION); 754 ZwDeleteValueKey(parametersKey, &valueName); 755 756 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MINOR_VERSION); 757 ZwDeleteValueKey(parametersKey, &valueName); 758 759 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_BUILD_NUMBER); 760 ZwDeleteValueKey(parametersKey, &valueName); 761 762 ZwDeleteKey(parametersKey); 763 764out: 765 if (driverExtension->ParametersRegistryPath.Buffer != NULL) { 766 ExFreePool(driverExtension->ParametersRegistryPath.Buffer); 767 } 768 769 if (driverKey != NULL) { 770 ZwClose(driverKey); 771 } 772 773 if (parametersKey != NULL) { 774 ZwClose(parametersKey); 775 } 776 777 return; 778}