1 2 /*++ 3 4 Copyright (c) Microsoft Corporation 5 6 Module Name: 7 8 globals.cpp 9 10 Abstract: 11 12 This contains all Driver Frameworks configuration globals. 13 14 Author: 15 16 17 18 19 Environment: 20 21 Both kernel and user mode 22 23 Revision History: 24 25 26 27 28 29 30 31 32 33 34 35 36 37 --*/ 38 39 40 #include "fxobjectpch.hpp" 41 42 // Tracing support 43 extern "C" { 44 #if defined(EVENT_TRACING) 45 #include "globals.tmh" 46 #endif 47 } 48 49 extern "C" { 50 51 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 52 VOID 53 VerifierPageLockHandle ( 54 VOID 55 ); 56 #ifdef ALLOC_PRAGMA 57 #pragma alloc_text(WDF_FX_VF_SECTION_NAME, VerifierPageLockHandle) 58 #endif 59 #endif 60 61 // 62 // Private methods. 63 // 64 65 VOID 66 FxLibraryGlobalsQueryRegistrySettings( 67 VOID 68 ); 69 70 VOID 71 FxRegistrySettingsInitialize( 72 __inout PFX_DRIVER_GLOBALS FxDriverGlobals, 73 __in PCUNICODE_STRING RegistryPath, 74 __in BOOLEAN WindowsVerifierOn 75 ); 76 77 _Must_inspect_result_ 78 FxObjectDebugInfo* 79 FxVerifierGetObjectDebugInfo( 80 __in HANDLE Key, 81 __in PFX_DRIVER_GLOBALS FxDriverGlobals 82 ); 83 84 VOID 85 FxVerifierQueryTrackPower( 86 __in HANDLE Key, 87 __out FxTrackPowerOption* TrackPower 88 ); 89 90 // 91 // Global allocation tracker 92 // 93 FX_POOL FxPoolFrameworks; 94 95 FxLibraryGlobalsType FxLibraryGlobals = { 0 }; 96 97 // 98 // These are defined in FxObjectInfo.cpp to account for the facts that 99 // 1. FxObjectInfo array is different for UMDF and KMDF, 100 // 2. and not all the types are available in the common code 101 // 102 extern const FX_OBJECT_INFO FxObjectsInfo[]; 103 extern ULONG FxObjectsInfoCount; 104 105 // 106 // Prevent compiler/linker/BBT from optimizing the global variable away 107 // 108 #if defined(_M_IX86) 109 #pragma comment(linker, "/include:_FxObjectsInfoCount") 110 #else 111 #pragma comment(linker, "/include:FxObjectsInfoCount") 112 #endif 113 114 115 _Must_inspect_result_ 116 BOOLEAN 117 FxVerifyObjectTypeInTable( 118 __in USHORT ObjectType 119 ) 120 { 121 ULONG i; 122 123 for (i = 0; i < FxObjectsInfoCount; i++) { 124 if (ObjectType == FxObjectsInfo[i].ObjectType) { 125 return TRUE; 126 } 127 else if (ObjectType > FxObjectsInfo[i].ObjectType) { 128 continue; 129 } 130 131 return FALSE; 132 } 133 134 return FALSE; 135 } 136 137 _Must_inspect_result_ 138 FxObjectDebugInfo* 139 FxVerifyAllocateDebugInfo( 140 __in LPWSTR HandleNameList, 141 __in PFX_DRIVER_GLOBALS FxDriverGlobals 142 ) 143 144 /*++ 145 146 Routine Description: 147 Allocates an array of FxObjectDebugInfo's. The length of this array is the 148 same length as FxObjectsInfo. The array is sorted the same as 149 FxObjectDebugInfo, ObjectInfo is ascending in the list. 150 151 If HandleNameList's first string is "*", we treat this as a wildcard and 152 track all external handles. 153 154 Arguments: 155 HandleNameList - a multi-sz of handle names. It is assumed the multi sz is 156 well formed. 157 158 Return Value: 159 a pointer allocated by ExAllocatePoolWithTag. The caller is responsible for 160 eventually freeing the pointer by calling ExFreePool. 161 162 --*/ 163 164 { 165 FxObjectDebugInfo* pInfo; 166 PWCHAR pCur; 167 ULONG i, length; 168 BOOLEAN all; 169 170 // 171 // check to see if the multi sz is empty 172 // 173 if (*HandleNameList == NULL) { 174 return NULL; 175 } 176 177 length = sizeof(FxObjectDebugInfo) * FxObjectsInfoCount; 178 179 // 180 // Freed with ExFreePool in FxFreeDriverGlobals. Must be non paged because 181 // objects can be allocated at IRQL > PASSIVE_LEVEL. 182 // 183 pInfo = (FxObjectDebugInfo*) MxMemory::MxAllocatePoolWithTag(NonPagedPool, 184 length, 185 FxDriverGlobals->Tag); 186 187 if (pInfo == NULL) { 188 return NULL; 189 } 190 191 all = *HandleNameList == L'*' ? TRUE : FALSE; 192 193 RtlZeroMemory(pInfo, length); 194 195 // 196 // Iterate over all of the objects in our internal array. We iterate over 197 // this array instead of the multi sz list b/c this way we only convert 198 // each ANSI string to UNICODE once. 199 // 200 for (i = 0; i < FxObjectsInfoCount; i++) { 201 UNICODE_STRING objectName; 202 WCHAR ubuffer[40]; 203 STRING string; 204 205 pInfo[i].ObjectType = FxObjectsInfo[i].ObjectType; 206 207 // 208 // If this is an internal object, just continue past it 209 // 210 if (FxObjectsInfo[i].HandleName == NULL) { 211 continue; 212 } 213 214 // 215 // Short circuit if we are wildcarding 216 // 217 if (all) { 218 pInfo[i].u.DebugFlags |= FxObjectDebugTrackReferences; 219 continue; 220 } 221 222 RtlInitAnsiString(&string, FxObjectsInfo[i].HandleName); 223 224 RtlZeroMemory(ubuffer, sizeof(ubuffer)); 225 objectName.Buffer = ubuffer; 226 objectName.Length = 0; 227 objectName.MaximumLength = sizeof(ubuffer); 228 229 // 230 // Conversion failed, just continue. Failure is not critical to 231 // returning the list. 232 // 233 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&objectName, 234 &string, 235 FALSE))) { 236 continue; 237 } 238 239 // 240 // Now iterate over the multi sz list, comparing handle strings in the 241 // list against the current object name. 242 // 243 pCur = HandleNameList; 244 245 while (*pCur != UNICODE_NULL) { 246 UNICODE_STRING handleName; 247 248 RtlInitUnicodeString(&handleName, pCur); 249 250 // 251 // Increment to the next string now. Add one so that we skip past 252 // terminating null for this sz as well. 253 // Length is the number of bytes, not the number of characters. 254 // 255 pCur += handleName.Length / sizeof(WCHAR) + 1; 256 257 // 258 // Case insensitive compare 259 // 260 if (RtlCompareUnicodeString(&handleName, &objectName, TRUE) == 0) { 261 pInfo[i].u.DebugFlags |= FxObjectDebugTrackReferences; 262 break; 263 } 264 } 265 } 266 267 return pInfo; 268 } 269 270 VOID 271 FxDriverGlobalsInitializeDebugExtension( 272 __inout PFX_DRIVER_GLOBALS FxDriverGlobals, 273 __in_opt HANDLE Key 274 ) 275 { 276 FxDriverGlobalsDebugExtension* pExtension; 277 278 // 279 // The wdf subkey may not be present for inbox drivers that do not use inf. 280 // Since Mdl tracking doen't need regsitry info we go ahead and allocate 281 // debug extension for use in Mdl tracking. Tag tracker depends on registry 282 // info and it won't be available if registry info is not present. 283 // 284 285 pExtension = (FxDriverGlobalsDebugExtension*) MxMemory::MxAllocatePoolWithTag( 286 NonPagedPool, sizeof(FxDriverGlobalsDebugExtension), FxDriverGlobals->Tag); 287 288 if (pExtension == NULL) { 289 return; 290 } 291 292 *pExtension = {}; 293 294 pExtension->AllocatedTagTrackersLock.Initialize(); 295 296 InitializeListHead(&pExtension->AllocatedTagTrackersListHead); 297 298 pExtension->TrackPower = FxTrackPowerNone; 299 300 FxDriverGlobals->DebugExtension = pExtension; 301 302 if (Key != NULL) { 303 pExtension->ObjectDebugInfo = FxVerifierGetObjectDebugInfo( 304 Key, 305 FxDriverGlobals 306 ); 307 FxVerifierQueryTrackPower(Key, &pExtension->TrackPower); 308 } 309 310 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 311 KeInitializeSpinLock(&pExtension->AllocatedMdlsLock); 312 #endif 313 } 314 315 PCSTR 316 FxObjectTypeToHandleName( 317 __in WDFTYPE ObjectType 318 ) 319 { 320 ULONG i; 321 322 for (i = 0; i < FxObjectsInfoCount; i++) { 323 if (ObjectType == FxObjectsInfo[i].ObjectType) { 324 return FxObjectsInfo[i].HandleName; 325 } 326 else if (ObjectType > FxObjectsInfo[i].ObjectType) { 327 continue; 328 } 329 330 return NULL; 331 } 332 333 return NULL; 334 } 335 336 _Must_inspect_result_ 337 BOOLEAN 338 FxVerifierGetTrackReferences( 339 __in FxObjectDebugInfo* DebugInfo, 340 __in WDFTYPE ObjectType 341 ) 342 343 /*++ 344 345 Routine Description: 346 For a given object type, returns to the caller if it should track references 347 to the object. 348 349 Arguments: 350 DebugInfo - array of object debug info to search through 351 ObjectType - the type of the object to check 352 353 Return Value: 354 TRUE if references should be tracked, FALSE otherwise 355 356 --*/ 357 358 { 359 ULONG i; 360 361 // 362 // Array size of DebugInfo is the same size as FxObjectsInfo 363 // 364 for (i = 0; i < FxObjectsInfoCount; i++) { 365 if (ObjectType == DebugInfo[i].ObjectType) { 366 return FLAG_TO_BOOL(DebugInfo[i].u.DebugFlags, 367 FxObjectDebugTrackReferences); 368 } 369 else if (ObjectType > FxObjectsInfo[i].ObjectType) { 370 continue; 371 } 372 373 return FALSE; 374 } 375 376 return FALSE; 377 } 378 379 380 VOID 381 FxVerifyObjectTableIsSorted( 382 VOID 383 ) 384 { 385 ULONG i; 386 USHORT prevType; 387 388 prevType = FxObjectsInfo[0].ObjectType; 389 390 for (i = 1; i < FxObjectsInfoCount; i++) { 391 if (prevType >= FxObjectsInfo[i].ObjectType) { 392 ASSERTMSG("FxObjectsInfo table is not in sorted order\n", 393 prevType < FxObjectsInfo[i].ObjectType); 394 } 395 396 prevType = FxObjectsInfo[i].ObjectType; 397 } 398 } 399 400 typedef 401 NTSTATUS 402 (*PFN_RTL_GET_VERSION)( 403 __out PRTL_OSVERSIONINFOW VersionInformation 404 ); 405 406 typedef 407 NTSTATUS 408 (*PFN_RTL_VERIFY_VERSION_INFO)( 409 __in PRTL_OSVERSIONINFOEXW VersionInfo, 410 __in ULONG TypeMask, 411 __in ULONGLONG ConditionMask 412 ); 413 414 typedef 415 ULONGLONG 416 (*PFN_VER_SET_CONDITION_MASK)( 417 __in ULONGLONG ConditionMask, 418 __in ULONG TypeMask, 419 __in UCHAR Condition 420 ); 421 422 VOID 423 FxLibraryGlobalsVerifyVersion( 424 VOID 425 ) 426 { 427 RTL_OSVERSIONINFOEXW info; 428 PFN_RTL_VERIFY_VERSION_INFO pRtlVerifyVersionInfo; 429 PFN_VER_SET_CONDITION_MASK pVerSetConditionMask; 430 ULONGLONG condition; 431 NTSTATUS status; 432 433 pRtlVerifyVersionInfo = (PFN_RTL_VERIFY_VERSION_INFO) 434 Mx::MxGetSystemRoutineAddress(MAKE_MX_FUNC_NAME("RtlVerifyVersionInfo")); 435 436 if (pRtlVerifyVersionInfo == NULL) { 437 return; 438 } 439 440 pVerSetConditionMask = (PFN_VER_SET_CONDITION_MASK) 441 Mx::MxGetSystemRoutineAddress(MAKE_MX_FUNC_NAME("VerSetConditionMask")); 442 443 // 444 // Check for Win8 (6.2) and later for passive-level interrupt support. 445 // 446 RtlZeroMemory(&info, sizeof(info)); 447 info.dwOSVersionInfoSize = sizeof(info); 448 info.dwMajorVersion = 6; 449 info.dwMinorVersion = 2; 450 451 condition = 0; 452 condition = pVerSetConditionMask(condition, VER_MAJORVERSION, VER_GREATER_EQUAL); 453 condition = pVerSetConditionMask(condition, VER_MINORVERSION, VER_GREATER_EQUAL); 454 455 status = pRtlVerifyVersionInfo(&info, 456 VER_MAJORVERSION | VER_MINORVERSION, 457 condition); 458 if (NT_SUCCESS(status)) { 459 FxLibraryGlobals.PassiveLevelInterruptSupport = TRUE; 460 } 461 } 462 463 VOID 464 FxLibraryGlobalsQueryRegistrySettings( 465 VOID 466 ) 467 { 468 FxAutoRegKey hWdf; 469 NTSTATUS status = STATUS_SUCCESS; 470 DECLARE_CONST_UNICODE_STRING(path, WDF_REGISTRY_BASE_PATH); 471 DECLARE_CONST_UNICODE_STRING(ifrDisabledName, WDF_GLOBAL_VALUE_IFRDISABLED); 472 ULONG ifrDisabled = 0; 473 474 status = FxRegKey::_OpenKey(NULL, &path, &hWdf.m_Key, KEY_READ); 475 if (!NT_SUCCESS(status)) { 476 goto exit; 477 } 478 479 status = FxRegKey::_QueryULong(hWdf.m_Key, &ifrDisabledName, &ifrDisabled); 480 if (!NT_SUCCESS(status)) { 481 goto exit; 482 } 483 484 if (ifrDisabled == 1) { 485 FxLibraryGlobals.IfrDisabled = TRUE; 486 } 487 488 exit: 489 return; 490 } 491 492 _Must_inspect_result_ 493 NTSTATUS 494 FxLibraryGlobalsCommission( 495 VOID 496 ) 497 { 498 PFN_RTL_GET_VERSION pRtlGetVersion; 499 NTSTATUS status; 500 501 // 502 // Global initialization for mode-agnostic primitives library 503 // 504 Mx::MxGlobalInit(); 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 521 FxLibraryGlobals.IsUserModeFramework = FALSE; 522 #else 523 FxLibraryGlobals.IsUserModeFramework = TRUE; 524 #endif 525 526 // 527 // IFR is enabled by default 528 // 529 FxLibraryGlobals.IfrDisabled = FALSE; 530 531 // 532 // Query global WDF settings (both KMDF and UMDF). 533 // 534 FxLibraryGlobalsQueryRegistrySettings(); 535 536 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 537 UNICODE_STRING funcName; 538 539 // For DSF support. 540 RtlInitUnicodeString(&funcName, L"IoConnectInterruptEx"); 541 FxLibraryGlobals.IoConnectInterruptEx = (PFN_IO_CONNECT_INTERRUPT_EX) 542 MmGetSystemRoutineAddress(&funcName); 543 544 RtlInitUnicodeString(&funcName, L"IoDisconnectInterruptEx"); 545 FxLibraryGlobals.IoDisconnectInterruptEx = (PFN_IO_DISCONNECT_INTERRUPT_EX) 546 MmGetSystemRoutineAddress(&funcName); 547 548 // 32 bit: W2k and forward. 549 // 64 bit: W2k -> Windows Server 2008 (obsolete otherwise). 550 RtlInitUnicodeString(&funcName, L"KeQueryActiveProcessors"); 551 FxLibraryGlobals.KeQueryActiveProcessors = (PFN_KE_QUERY_ACTIVE_PROCESSORS) 552 MmGetSystemRoutineAddress(&funcName); 553 554 RtlInitUnicodeString(&funcName, L"KeSetTargetProcessorDpc"); 555 FxLibraryGlobals.KeSetTargetProcessorDpc = (PFN_KE_SET_TARGET_PROCESSOR_DPC) 556 MmGetSystemRoutineAddress(&funcName); 557 558 // These should always be there (obsolete in 64 bit Win 7 and forward). 559 ASSERT(FxLibraryGlobals.KeQueryActiveProcessors != NULL && 560 FxLibraryGlobals.KeSetTargetProcessorDpc != NULL); 561 562 // Win 7 and forward. 563 RtlInitUnicodeString(&funcName, L"KeQueryActiveGroupCount"); 564 if (MmGetSystemRoutineAddress(&funcName) != NULL) { 565 FxLibraryGlobals.ProcessorGroupSupport = TRUE; 566 } 567 568 // Win 7 and forward. 569 RtlInitUnicodeString(&funcName, L"KeSetCoalescableTimer"); 570 FxLibraryGlobals.KeSetCoalescableTimer = (PFN_KE_SET_COALESCABLE_TIMER) 571 MmGetSystemRoutineAddress(&funcName); 572 573 // Win 7 and forward. 574 RtlInitUnicodeString(&funcName, L"IoUnregisterPlugPlayNotificationEx"); 575 FxLibraryGlobals.IoUnregisterPlugPlayNotificationEx = (PFN_IO_UNREGISTER_PLUGPLAY_NOTIFICATION_EX) 576 MmGetSystemRoutineAddress(&funcName); 577 578 // Win 8 and forward 579 RtlInitUnicodeString(&funcName, L"PoFxRegisterDevice"); 580 FxLibraryGlobals.PoxRegisterDevice = 581 (PFN_POX_REGISTER_DEVICE) MmGetSystemRoutineAddress(&funcName); 582 583 // Win 8 and forward 584 RtlInitUnicodeString(&funcName, L"PoFxStartDevicePowerManagement"); 585 FxLibraryGlobals.PoxStartDevicePowerManagement = 586 (PFN_POX_START_DEVICE_POWER_MANAGEMENT) 587 MmGetSystemRoutineAddress(&funcName); 588 589 // Win 8 and forward 590 RtlInitUnicodeString(&funcName, L"PoFxUnregisterDevice"); 591 FxLibraryGlobals.PoxUnregisterDevice = 592 (PFN_POX_UNREGISTER_DEVICE) 593 MmGetSystemRoutineAddress(&funcName); 594 595 // Win 8 and forward 596 RtlInitUnicodeString(&funcName, L"PoFxActivateComponent"); 597 FxLibraryGlobals.PoxActivateComponent = (PFN_POX_ACTIVATE_COMPONENT) 598 MmGetSystemRoutineAddress(&funcName); 599 600 // Win 8 and forward 601 RtlInitUnicodeString(&funcName, L"PoFxIdleComponent"); 602 FxLibraryGlobals.PoxIdleComponent = (PFN_POX_IDLE_COMPONENT) 603 MmGetSystemRoutineAddress(&funcName); 604 605 // Win 8 and forward 606 RtlInitUnicodeString(&funcName, L"PoFxReportDevicePoweredOn"); 607 FxLibraryGlobals.PoxReportDevicePoweredOn = 608 (PFN_POX_REPORT_DEVICE_POWERED_ON) MmGetSystemRoutineAddress(&funcName); 609 610 // Win 8 and forward 611 RtlInitUnicodeString(&funcName, L"PoFxCompleteIdleState"); 612 FxLibraryGlobals.PoxCompleteIdleState = 613 (PFN_POX_COMPLETE_IDLE_STATE) MmGetSystemRoutineAddress(&funcName); 614 615 // Win 8 and forward 616 RtlInitUnicodeString(&funcName, L"PoFxCompleteIdleCondition"); 617 FxLibraryGlobals.PoxCompleteIdleCondition = 618 (PFN_POX_COMPLETE_IDLE_CONDITION) MmGetSystemRoutineAddress(&funcName); 619 620 // Win 8 and forward 621 RtlInitUnicodeString(&funcName, L"PoFxCompleteDevicePowerNotRequired"); 622 FxLibraryGlobals.PoxCompleteDevicePowerNotRequired = 623 (PFN_POX_COMPLETE_DEVICE_POWER_NOT_REQUIRED) MmGetSystemRoutineAddress(&funcName); 624 625 // Win 8 and forward 626 RtlInitUnicodeString(&funcName, L"PoFxSetDeviceIdleTimeout"); 627 FxLibraryGlobals.PoxSetDeviceIdleTimeout = 628 (PFN_POX_SET_DEVICE_IDLE_TIMEOUT) MmGetSystemRoutineAddress(&funcName); 629 630 // Win 8 and forward 631 RtlInitUnicodeString(&funcName, L"IoReportInterruptActive"); 632 FxLibraryGlobals.IoReportInterruptActive = 633 (PFN_IO_REPORT_INTERRUPT_ACTIVE) MmGetSystemRoutineAddress(&funcName); 634 635 // Win 8 and forward 636 RtlInitUnicodeString(&funcName, L"IoReportInterruptInactive"); 637 FxLibraryGlobals.IoReportInterruptInactive = 638 (PFN_IO_REPORT_INTERRUPT_INACTIVE) MmGetSystemRoutineAddress(&funcName); 639 640 // Win 8.2 and forward 641 RtlInitUnicodeString(&funcName, L"VfCheckNxPoolType"); 642 FxLibraryGlobals.VfCheckNxPoolType = 643 (PFN_VF_CHECK_NX_POOL_TYPE) MmGetSystemRoutineAddress(&funcName); 644 645 #endif //((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 646 647 FxLibraryGlobals.OsVersionInfo.dwOSVersionInfoSize = sizeof(FxLibraryGlobals.OsVersionInfo); 648 649 // User/Kernel agnostic. 650 651 pRtlGetVersion = (PFN_RTL_GET_VERSION) 652 Mx::MxGetSystemRoutineAddress(MAKE_MX_FUNC_NAME("RtlGetVersion")); 653 654 ASSERT(pRtlGetVersion != NULL); 655 pRtlGetVersion((PRTL_OSVERSIONINFOW) &FxLibraryGlobals.OsVersionInfo); 656 FxLibraryGlobalsVerifyVersion(); 657 658 // 659 // Initialize power management-related stuff. 660 // 661 RtlZeroMemory(&FxLibraryGlobals.MachineSleepStates[0], 662 sizeof(FxLibraryGlobals.MachineSleepStates)); 663 664 // 665 // Insure that the FxObject is layed-up correctly. 666 // 667 FxVerifyObjectTableIsSorted(); 668 669 // 670 // Initialize the list of FxDriverGlobals. 671 // This is essentially the list of drivers on this WDF version. 672 // 673 InitializeListHead(&FxLibraryGlobals.FxDriverGlobalsList); 674 FxLibraryGlobals.FxDriverGlobalsListLock.Initialize(); 675 676 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 677 // 678 // Register for the global (library) bugcheck callbacks. 679 // 680 FxInitializeBugCheckDriverInfo(); 681 #ifdef EVENT_TRACING // __REACTOS__ 682 // 683 // Init driver usage tracker. This tracker is used by the debug dump 684 // callback routines for finding the driver's dump log file to write 685 // in the minidump. Ignore any tracker's errors. 686 // 687 (VOID)FxLibraryGlobals.DriverTracker.Initialize(); 688 689 // 690 // Initialize enhanced-verifier section handle 691 // 692 FxLibraryGlobals.VerifierSectionHandle = NULL; 693 FxLibraryGlobals.VerifierSectionHandleRefCount = 0; 694 695 // 696 // Retrieve a pointer to the data structure that cotains trace routines 697 // corresponding to WdfNotifyRoutinesClass from the SystemTraceProvider 698 // that we'll use for perf tracing of WDF operations. The trace 699 // routines inside the structuyre are present only when tracing is enabled 700 // by some trace client (e.g. tracelog or xperf) for WDF specific perf 701 // groups. Note that no unregistration is necessary. 702 // 703 status = WmiQueryTraceInformation(WdfNotifyRoutinesClass, 704 &FxLibraryGlobals.PerfTraceRoutines, 705 sizeof(PWMI_WDF_NOTIFY_ROUTINES), 706 NULL, 707 NULL); 708 709 if (!NT_SUCCESS(status)) { 710 // 711 // WDF trace routines are available only on win8+, so failure is 712 // expected on pre-Win8 OS. Use the dummy routines on failure. 713 // 714 RtlZeroMemory(&FxLibraryGlobals.DummyPerfTraceRoutines, 715 sizeof(WMI_WDF_NOTIFY_ROUTINES)); 716 FxLibraryGlobals.DummyPerfTraceRoutines.Size = 717 sizeof(WMI_WDF_NOTIFY_ROUTINES); 718 FxLibraryGlobals.PerfTraceRoutines = 719 &FxLibraryGlobals.DummyPerfTraceRoutines; 720 status = STATUS_SUCCESS; 721 } 722 723 // 724 // The Size member of WMI_WDF_NOTIFY_ROUTINES allows versioning. When 725 // the WMI_WDF_NOTIFY_ROUTINES structure is revised with additional 726 // members in future OS versions, the Size member will allow validating 727 // the various versions, and initializeing the structure correctly. 728 // 729 ASSERT(FxLibraryGlobals.PerfTraceRoutines->Size >= 730 sizeof(WMI_WDF_NOTIFY_ROUTINES)); 731 #else 732 status = STATUS_SUCCESS; // __REACTOS__ 733 #endif // EVENT_TRACING 734 #else 735 status = STATUS_SUCCESS; 736 #endif 737 738 return status; 739 } 740 741 VOID 742 FxLibraryGlobalsDecommission( 743 VOID 744 ) 745 { 746 // 747 // Assure the all driver's FxDriverGlobals have been freed. 748 // 749 ASSERT(IsListEmpty(&FxLibraryGlobals.FxDriverGlobalsList)); 750 751 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 752 // 753 // Cleanup for the driver usage tracker. 754 // 755 FxLibraryGlobals.DriverTracker.Uninitialize(); 756 757 // 758 // Deregister from the global (library) bugcheck callbacks. 759 // 760 FxUninitializeBugCheckDriverInfo(); 761 #endif 762 763 FxLibraryGlobals.FxDriverGlobalsListLock.Uninitialize(); 764 765 return; 766 } 767 768 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 769 // 770 // This function is only used to lock down verifier section code in memory. 771 // It uses the #pragma alloc_text(...) style for paging. 772 // 773 VOID 774 VerifierPageLockHandle ( 775 VOID 776 ) 777 { 778 PAGED_CODE_LOCKED(); 779 DO_NOTHING(); 780 } 781 782 VOID 783 LockVerifierSection( 784 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 785 _In_ PCUNICODE_STRING RegistryPath 786 ) 787 { 788 LONG count; 789 790 // 791 // This asserts makes sure the struct is not pack(1) and the counter 792 // is correctly aligned on a 32 bit boundary. 793 // 794 C_ASSERT((FIELD_OFFSET(FxLibraryGlobalsType, VerifierSectionHandleRefCount) 795 % __alignof(LONG)) == 0); 796 797 count = InterlockedIncrement(&FxLibraryGlobals.VerifierSectionHandleRefCount); 798 ASSERT(count > 0); 799 800 // 801 // If verifier section is unlocked, lock it in. 802 // 803 if(FxLibraryGlobals.VerifierSectionHandle == NULL) { 804 // 805 //First time verifier section is being locked. 806 // 807 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDRIVER, 808 "First time Locking (%d) in Verifier Paged Memory " 809 "from %!wZ! from driver globals %p", 810 count, RegistryPath, FxDriverGlobals); 811 // 812 // VerifierLockHandle is a function that we use to lock in all the code from it's section 813 // since all the verifier code is in the same section as VerifierLockHandle. 814 // 815 FxLibraryGlobals.VerifierSectionHandle = MmLockPagableCodeSection((PVOID)VerifierPageLockHandle); 816 } 817 else { 818 MmLockPagableSectionByHandle(FxLibraryGlobals.VerifierSectionHandle); 819 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDRIVER, 820 "Increment Lock counter (%d) for Verifier Paged Memory " 821 "from %!wZ! from driver globals %p", 822 count, RegistryPath, FxDriverGlobals); 823 } 824 } 825 826 VOID 827 UnlockVerifierSection( 828 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals 829 ) 830 { 831 if( FxLibraryGlobals.VerifierSectionHandle != NULL) { 832 LONG count; 833 834 count = InterlockedDecrement(&FxLibraryGlobals.VerifierSectionHandleRefCount); 835 ASSERT(count >= 0); 836 837 MmUnlockPagableImageSection(FxLibraryGlobals.VerifierSectionHandle); 838 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDRIVER, 839 "Decrement UnLock counter (%d) for Verifier Paged Memory " 840 "with driver globals %p", 841 count, FxDriverGlobals); 842 } 843 } 844 #endif 845 846 _Must_inspect_result_ 847 NTSTATUS 848 FxInitialize( 849 __inout PFX_DRIVER_GLOBALS FxDriverGlobals, 850 __in MdDriverObject DriverObject, 851 __in PCUNICODE_STRING RegistryPath, 852 __in_opt PWDF_DRIVER_CONFIG DriverConfig 853 ) 854 855 /*++ 856 857 Routine Description: 858 859 This is the global framework initialization routine. 860 861 This is called when the framework is loaded, and by 862 any drivers that use the framework. 863 864 It is safe to call if already initialized, to handle 865 cases where multiple drivers are sharing a common 866 kernel DLL. 867 868 This method is used instead of relying on C++ static class 869 constructors in kernel mode. 870 871 Arguments: 872 873 874 Returns: 875 876 NTSTATUS 877 878 --*/ 879 880 { 881 NTSTATUS status; 882 BOOLEAN windowsVerifierOn = FALSE; 883 884 UNREFERENCED_PARAMETER(DriverConfig); 885 886 // 887 // Check if windows driver verifier is on for this driver 888 // We need this when initializing wdf verifier 889 // 890 windowsVerifierOn = IsWindowsVerifierOn(DriverObject); 891 892 // 893 // Get registry values first since these effect the 894 // rest of initialization 895 // 896 FxRegistrySettingsInitialize(FxDriverGlobals, 897 RegistryPath, 898 windowsVerifierOn); 899 900 // 901 // Initialize IFR logging 902 // 903 // FxIFRStart(FxDriverGlobals, RegistryPath, DriverObject); __REACTOS__ 904 905 DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 906 "Initialize globals for %!wZ!", RegistryPath); 907 908 // 909 // Only first one initializes the frameworks globals 910 // 911 status = FxPoolPackageInitialize(FxDriverGlobals); 912 if (!NT_SUCCESS(status)) { 913 // 914 // FxPoolPackageInitialize logs a message in case of failure so 915 // we don't need to log failure here. 916 // 917 // FxIFRStop(FxDriverGlobals); __REACTOS__ 918 return status; 919 } 920 921 // 922 // Lock verifier package 923 // 924 FxVerifierLockInitialize(FxDriverGlobals); 925 926 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 927 // 928 // Cache driver info for bugcheck callback. 929 // 930 FxCacheBugCheckDriverInfo(FxDriverGlobals); 931 932 // 933 // Register for bugcheck callbacks. 934 // 935 FxRegisterBugCheckCallback(FxDriverGlobals, DriverObject); 936 #endif 937 938 if (NULL != RegistryPath) { 939 if (FALSE == FxDriverGlobals->IsCorrectVersionRegistered(RegistryPath)) 940 FxDriverGlobals->RegisterClientVersion(RegistryPath); 941 } 942 943 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 944 if(FxDriverGlobals->FxVerifierOn){ 945 LockVerifierSection(FxDriverGlobals, RegistryPath); 946 } 947 #endif 948 949 return STATUS_SUCCESS; 950 } 951 952 BOOLEAN 953 IsWindowsVerifierOn( 954 _In_ MdDriverObject DriverObject 955 ) 956 { 957 BOOLEAN windowsVerifierOn = FALSE; 958 959 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 960 // 961 // Check if windows driver verifier is on for this driver 962 // We need this when initializing wdf verifier 963 // 964 windowsVerifierOn = MmIsDriverVerifying(DriverObject) ? TRUE: FALSE; 965 966 #else 967 UNREFERENCED_PARAMETER(DriverObject); 968 969 // 970 // For user-mode we check if app verifier's verifier.dll is loaded in this 971 // process (since app verifier doesn't provide any other way to detect its 972 // presence). 973 // 974 windowsVerifierOn = (GetModuleHandleW(L"verifier.dll") == NULL ? FALSE : TRUE); 975 #endif 976 977 return windowsVerifierOn; 978 } 979 980 VOID 981 FxDestroy( 982 __in PFX_DRIVER_GLOBALS FxDriverGlobals 983 ) 984 985 /*++ 986 987 Routine Description: 988 989 This is the global framework uninitialization routine. 990 991 It is here for symmetry, and to allow a shared DLL based frameworks 992 to unload safely. 993 994 Arguments: 995 996 997 Returns: 998 999 NTSTATUS 1000 1001 --*/ 1002 1003 { 1004 // 1005 // Release the last reference. 1006 // 1007 FxDriverGlobals->RELEASE((PVOID)FxDestroy); 1008 1009 // 1010 // Wait for everyone else to be done. 1011 // 1012 Mx::MxEnterCriticalRegion(); 1013 FxDriverGlobals->DestroyEvent.WaitFor(Executive, KernelMode, FALSE, NULL); 1014 Mx::MxLeaveCriticalRegion(); 1015 1016 // 1017 // Lock verifier package 1018 // 1019 FxVerifierLockDestroy(FxDriverGlobals); 1020 1021 // 1022 // Cleanup frameworks structures 1023 // 1024 FxPoolPackageDestroy(FxDriverGlobals); 1025 1026 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 1027 // 1028 // Deregister from the bugcheck callbacks. 1029 // 1030 FxUnregisterBugCheckCallback(FxDriverGlobals); 1031 1032 // 1033 // Purge driver info from bugcheck data. 1034 // 1035 FxPurgeBugCheckDriverInfo(FxDriverGlobals); 1036 #endif 1037 1038 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE)) 1039 // 1040 // unlock verifier image sections 1041 // 1042 if(FxDriverGlobals->FxVerifierOn){ 1043 UnlockVerifierSection(FxDriverGlobals); 1044 } 1045 #endif 1046 1047 return; 1048 } 1049 1050 _Must_inspect_result_ 1051 PWDF_DRIVER_GLOBALS 1052 FxAllocateDriverGlobals( 1053 VOID 1054 ) 1055 { 1056 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1057 // KIRQL irql; 1058 NTSTATUS status; 1059 1060 pFxDriverGlobals = (PFX_DRIVER_GLOBALS) 1061 MxMemory::MxAllocatePoolWithTag(NonPagedPool, sizeof(FX_DRIVER_GLOBALS), FX_TAG); 1062 1063 if (pFxDriverGlobals == NULL) { 1064 return NULL; 1065 } 1066 1067 *pFxDriverGlobals = {}; 1068 1069 pFxDriverGlobals->Refcnt = 1; 1070 1071 status = pFxDriverGlobals->DestroyEvent.Initialize(NotificationEvent, FALSE); 1072 #if (FX_CORE_MODE==FX_CORE_USER_MODE) 1073 if (!NT_SUCCESS(status)) { 1074 MxMemory::MxFreePool(pFxDriverGlobals); 1075 return NULL; 1076 } 1077 #else 1078 UNREFERENCED_PARAMETER(status); 1079 #endif 1080 1081 // 1082 // Initialize this new FxDriverGlobals structure. 1083 // 1084 #ifndef __REACTOS__ 1085 FxLibraryGlobals.FxDriverGlobalsListLock.Acquire(&irql); 1086 InsertHeadList(&FxLibraryGlobals.FxDriverGlobalsList, 1087 &pFxDriverGlobals->Linkage); 1088 FxLibraryGlobals.FxDriverGlobalsListLock.Release(irql); 1089 #endif 1090 1091 pFxDriverGlobals->WdfHandleMask = FxHandleValueMask; 1092 pFxDriverGlobals->WdfVerifierAllocateFailCount = (ULONG) -1; 1093 pFxDriverGlobals->Driver = NULL; 1094 pFxDriverGlobals->DebugExtension = NULL; 1095 pFxDriverGlobals->LibraryGlobals = &FxLibraryGlobals; 1096 pFxDriverGlobals->WdfLogHeader = NULL; 1097 1098 // 1099 // Verifier settings. Off by default. 1100 // 1101 pFxDriverGlobals->SetVerifierState(FALSE); 1102 1103 // 1104 // By default don't apply latest-version restricted verifier checks 1105 // to downlevel version drivers. 1106 // 1107 pFxDriverGlobals->FxVerifyDownlevel = FALSE; 1108 1109 // 1110 // Verbose is separate knob 1111 // 1112 pFxDriverGlobals->FxVerboseOn = FALSE; 1113 1114 // 1115 // Do not parent queue presented requests. 1116 // This performance optimization is on by default. 1117 // 1118 pFxDriverGlobals->FxRequestParentOptimizationOn = TRUE; 1119 1120 // 1121 // Enhanced verifier options. Off by default 1122 // 1123 pFxDriverGlobals->FxEnhancedVerifierOptions = 0; 1124 1125 // 1126 // If FxVerifierDbgBreakOnError is true, WaitForSignal interrupts the 1127 // execution of the system after waiting for the specified number 1128 // of seconds. Developer will have an opportunity to validate the state 1129 // of the driver when breakpoint is hit. Developer can continue to wait 1130 // by entering 'g' in the debugger. 1131 // 1132 pFxDriverGlobals->FxVerifierDbgWaitForSignalTimeoutInSec = 60; 1133 1134 // 1135 // Timeout used by the wake interrupt ISR in WaitForSignal to catch 1136 // scenarios where the interrupt ISR is blocked because the device stack 1137 // is taking too long to power up 1138 // 1139 pFxDriverGlobals->DbgWaitForWakeInterruptIsrTimeoutInSec = 60; 1140 1141 // 1142 // Minidump log related settings. 1143 // 1144 pFxDriverGlobals->FxForceLogsInMiniDump = FALSE; 1145 1146 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 1147 // pFxDriverGlobals->FxTrackDriverForMiniDumpLog = TRUE; 1148 pFxDriverGlobals->FxTrackDriverForMiniDumpLog = FALSE; // __REACTOS__ 1149 pFxDriverGlobals->IsUserModeDriver = FALSE; 1150 #else 1151 pFxDriverGlobals->FxTrackDriverForMiniDumpLog = FALSE; 1152 pFxDriverGlobals->IsUserModeDriver = TRUE; 1153 #endif 1154 1155 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 1156 // 1157 // Minidump driver info related settings. 1158 // 1159 pFxDriverGlobals->BugCheckDriverInfoIndex = 0; 1160 #endif 1161 1162 // 1163 // By default disable the support for device simulation framework (DSF). 1164 // 1165 pFxDriverGlobals->FxDsfOn = FALSE; 1166 1167 // 1168 // Allocate a telemetry context if a telemetry client is enabled, for any level/keyword. 1169 // 1170 pFxDriverGlobals->TelemetryContext = NULL; 1171 #ifdef EVENT_TRACING // __REACTOS__ 1172 if (TraceLoggingProviderEnabled(g_TelemetryProvider, 0 ,0)) { 1173 AllocAndInitializeTelemetryContext(&(pFxDriverGlobals->TelemetryContext)); 1174 } 1175 #endif 1176 1177 return &pFxDriverGlobals->Public; 1178 } 1179 1180 VOID 1181 FxFreeDriverGlobals( 1182 __in PWDF_DRIVER_GLOBALS DriverGlobals 1183 ) 1184 { 1185 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1186 KIRQL irql; 1187 1188 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); 1189 1190 FxLibraryGlobals.FxDriverGlobalsListLock.Acquire(&irql); 1191 RemoveEntryList(&pFxDriverGlobals->Linkage); 1192 InitializeListHead(&pFxDriverGlobals->Linkage); 1193 FxLibraryGlobals.FxDriverGlobalsListLock.Release(irql); 1194 1195 if (pFxDriverGlobals->DebugExtension != NULL) { 1196 1197 FxFreeAllocatedMdlsDebugInfo(pFxDriverGlobals->DebugExtension); 1198 1199 if (pFxDriverGlobals->DebugExtension->ObjectDebugInfo != NULL) { 1200 MxMemory::MxFreePool(pFxDriverGlobals->DebugExtension->ObjectDebugInfo); 1201 pFxDriverGlobals->DebugExtension->ObjectDebugInfo = NULL; 1202 } 1203 1204 pFxDriverGlobals->DebugExtension->AllocatedTagTrackersLock.Uninitialize(); 1205 1206 MxMemory::MxFreePool(pFxDriverGlobals->DebugExtension); 1207 pFxDriverGlobals->DebugExtension = NULL; 1208 } 1209 1210 // 1211 // Cleanup event b/c d'tor is not called for MxAllocatePoolWithTag. 1212 // 1213 pFxDriverGlobals->DestroyEvent.Uninitialize(); 1214 1215 if (NULL != pFxDriverGlobals->TelemetryContext) { 1216 MxMemory::MxFreePool(pFxDriverGlobals->TelemetryContext); 1217 pFxDriverGlobals->TelemetryContext = NULL; 1218 } 1219 1220 MxMemory::MxFreePool(pFxDriverGlobals); 1221 } 1222 1223 _Must_inspect_result_ 1224 FxObjectDebugInfo* 1225 FxVerifierGetObjectDebugInfo( 1226 __in HANDLE Key, 1227 __in PFX_DRIVER_GLOBALS FxDriverGlobals 1228 ) 1229 1230 /*++ 1231 1232 Routine Description: 1233 Attempts to open a value under the passed in key and create an array of 1234 FxObjectDebugInfo. 1235 1236 Arguments: 1237 Key - Registry key to query the value for 1238 1239 Return Value: 1240 NULL or a pointer which should be freed by the caller using ExFreePool 1241 1242 --*/ 1243 1244 { 1245 FxObjectDebugInfo* pInfo; 1246 PVOID dataBuffer; 1247 NTSTATUS status; 1248 ULONG length, type; 1249 DECLARE_CONST_UNICODE_STRING(valueName, L"TrackHandles"); 1250 1251 pInfo = NULL; 1252 type = REG_MULTI_SZ; 1253 length = 0; 1254 1255 // 1256 // Find out how big a buffer we need to allocate if the value is present 1257 // 1258 status = FxRegKey::_QueryValue(FxDriverGlobals, 1259 Key, 1260 &valueName, 1261 length, 1262 NULL, 1263 &length, 1264 &type); 1265 1266 // 1267 // We expect the list to be bigger then a standard partial, so if it is 1268 // not, just bail now. 1269 // 1270 if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) { 1271 return NULL; 1272 } 1273 1274 // 1275 // Pool can be paged b/c we are running at PASSIVE_LEVEL and we are going 1276 // to free it at the end of this function. 1277 // 1278 dataBuffer = MxMemory::MxAllocatePoolWithTag(PagedPool, length, FxDriverGlobals->Tag); 1279 if (dataBuffer == NULL) { 1280 return NULL; 1281 } 1282 1283 // 1284 // Requery now that we have a big enough buffer 1285 // 1286 status = FxRegKey::_QueryValue(FxDriverGlobals, 1287 Key, 1288 &valueName, 1289 length, 1290 dataBuffer, 1291 &length, 1292 &type); 1293 if (NT_SUCCESS(status)) { 1294 // 1295 // Verify that the data from the registry is a valid multi-sz string. 1296 // 1297 status = FxRegKey::_VerifyMultiSzString(FxDriverGlobals, 1298 &valueName, 1299 (PWCHAR) dataBuffer, 1300 length); 1301 } 1302 1303 if (NT_SUCCESS(status)) { 1304 #pragma prefast(push) 1305 #pragma prefast(suppress:__WARNING_PRECONDITION_NULLTERMINATION_VIOLATION, "FxRegKey::_VerifyMultiSzString makes sure the string is NULL-terminated") 1306 pInfo = FxVerifyAllocateDebugInfo((LPWSTR) dataBuffer, FxDriverGlobals); 1307 #pragma prefast(pop) 1308 1309 } 1310 1311 MxMemory::MxFreePool(dataBuffer); 1312 1313 return pInfo; 1314 } 1315 1316 VOID 1317 FxVerifierQueryTrackPower( 1318 __in HANDLE Key, 1319 __out FxTrackPowerOption* TrackPower 1320 ) 1321 { 1322 NTSTATUS status; 1323 ULONG value = 0; 1324 DECLARE_CONST_UNICODE_STRING(valueName, L"TrackPower"); 1325 1326 status = FxRegKey::_QueryULong(Key, &valueName, &value); 1327 if (NT_SUCCESS(status) && value < FxTrackPowerMaxValue) { 1328 *TrackPower = (FxTrackPowerOption)value; 1329 } 1330 else { 1331 *TrackPower = FxTrackPowerNone; 1332 } 1333 } 1334 1335 VOID 1336 FxOverrideDefaultVerifierSettings( 1337 __in HANDLE Key, 1338 __in LPWSTR Name, 1339 __out PBOOLEAN OverrideValue 1340 ) 1341 { 1342 UNICODE_STRING valueName; 1343 ULONG value = 0; 1344 1345 RtlInitUnicodeString(&valueName, Name); 1346 1347 if (NT_SUCCESS(FxRegKey::_QueryULong(Key, 1348 (PCUNICODE_STRING)&valueName, 1349 &value))) { 1350 if (value) { 1351 *OverrideValue = TRUE; 1352 } else { 1353 *OverrideValue = FALSE; 1354 } 1355 } 1356 1357 } 1358 1359 1360 VOID 1361 FxRegistrySettingsInitialize( 1362 __inout PFX_DRIVER_GLOBALS FxDriverGlobals, 1363 __in PCUNICODE_STRING RegistryPath, 1364 __in BOOLEAN WindowsVerifierOn 1365 ) 1366 1367 /*++ 1368 1369 Routine Description: 1370 1371 Initialize Driver Framework settings from the driver 1372 specific registry settings under 1373 1374 \REGISTRY\MACHINE\SYSTEM\ControlSetxxx\Services\<driver>\Parameters\Wdf 1375 1376 Arguments: 1377 1378 RegistryPath - Registry path passed to DriverEntry 1379 1380 --*/ 1381 1382 { 1383 NTSTATUS status; 1384 RTL_QUERY_REGISTRY_TABLE paramTable[10]; 1385 ULONG verifierOnValue; 1386 ULONG verifyDownlevelValue; 1387 ULONG verboseValue; 1388 ULONG allocateFailValue; 1389 ULONG forceLogsInMiniDump; 1390 ULONG trackDriverForMiniDumpLog; 1391 ULONG requestParentOptimizationOn; 1392 ULONG dsfValue; 1393 ULONG removeLockOptionFlags; 1394 ULONG zero = 0; 1395 ULONG max = 0xFFFFFFFF; 1396 ULONG defaultTrue = (ULONG) TRUE; 1397 ULONG i; 1398 ULONG timeoutValue = 0; 1399 FxAutoRegKey hDriver, hWdf; 1400 DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf"); 1401 1402 typedef NTSTATUS NTAPI QUERYFN( 1403 ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID); 1404 1405 QUERYFN* queryFn; 1406 1407 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 1408 UNICODE_STRING FunctionName; 1409 #endif 1410 1411 // 1412 // UMDF may not provide this registry path 1413 // 1414 if (NULL == RegistryPath) { 1415 return; 1416 } 1417 1418 status = FxRegKey::_OpenKey(NULL, RegistryPath, &hDriver.m_Key, KEY_READ); 1419 if (!NT_SUCCESS(status)) { 1420 return; 1421 } 1422 1423 status = FxRegKey::_OpenKey(hDriver.m_Key, ¶metersPath, &hWdf.m_Key, KEY_READ); 1424 if (!NT_SUCCESS(status)) { 1425 // 1426 // For version >= 1.9 we enable WDF verifier automatically when driver 1427 // verifier or app verifier is enabled. Since inbox drivers may not have 1428 // WDF subkey populated as they may not use INF, we need to enable 1429 // verifier even if we fail to open wdf subkey (if DriverVerifier is on). 1430 // 1431 if (FxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,9)) { 1432 // 1433 // Verifier settings are all or nothing. We currently do not support 1434 // turning on individual sub-verifiers. 1435 // 1436 FxDriverGlobals->SetVerifierState(WindowsVerifierOn); 1437 if (FxDriverGlobals->FxVerifierOn) { 1438 FxDriverGlobalsInitializeDebugExtension(FxDriverGlobals, NULL); 1439 } 1440 } 1441 1442 return; 1443 } 1444 1445 RtlZeroMemory (¶mTable[0], sizeof(paramTable)); 1446 i = 0; 1447 1448 verboseValue = 0; 1449 1450 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1451 paramTable[i].Name = L"VerboseOn"; 1452 paramTable[i].EntryContext = &verboseValue; 1453 paramTable[i].DefaultType = REG_DWORD; 1454 paramTable[i].DefaultData = &zero; 1455 paramTable[i].DefaultLength = sizeof(ULONG); 1456 1457 allocateFailValue = (ULONG) -1; 1458 i++; 1459 1460 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1461 paramTable[i].Name = L"VerifierAllocateFailCount"; 1462 paramTable[i].EntryContext = &allocateFailValue; 1463 paramTable[i].DefaultType = REG_DWORD; 1464 paramTable[i].DefaultData = &max; 1465 paramTable[i].DefaultLength = sizeof(ULONG); 1466 1467 verifierOnValue = 0; 1468 1469 // 1470 // If the client version is 1.9 or above, the defaut (i.e when 1471 // the key is not present) VerifierOn state is tied to the 1472 // driver verifier. 1473 // 1474 if (FxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,9)) { 1475 verifierOnValue = WindowsVerifierOn; 1476 } 1477 1478 i++; 1479 1480 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1481 paramTable[i].Name = L"VerifierOn"; 1482 paramTable[i].EntryContext = &verifierOnValue; 1483 paramTable[i].DefaultType = REG_DWORD; 1484 paramTable[i].DefaultData = &verifierOnValue; 1485 paramTable[i].DefaultLength = sizeof(ULONG); 1486 1487 verifyDownlevelValue = 0; 1488 i++; 1489 1490 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1491 paramTable[i].Name = L"VerifyDownLevel"; 1492 paramTable[i].EntryContext = &verifyDownlevelValue; 1493 paramTable[i].DefaultType = REG_DWORD; 1494 paramTable[i].DefaultData = &zero; 1495 paramTable[i].DefaultLength = sizeof(ULONG); 1496 1497 forceLogsInMiniDump = 0; 1498 i++; 1499 1500 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1501 paramTable[i].Name = L"ForceLogsInMiniDump"; 1502 paramTable[i].EntryContext = &forceLogsInMiniDump; 1503 paramTable[i].DefaultType = REG_DWORD; 1504 paramTable[i].DefaultData = &zero; 1505 paramTable[i].DefaultLength = sizeof(ULONG); 1506 1507 // 1508 // Track driver for minidump log: 1509 // Default for KMDF is on. 1510 // Default for UMDF is off. 1511 // 1512 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 1513 trackDriverForMiniDumpLog = (ULONG) TRUE; 1514 #else 1515 trackDriverForMiniDumpLog = 0; 1516 #endif 1517 i++; 1518 1519 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1520 paramTable[i].Name = L"TrackDriverForMiniDumpLog"; 1521 paramTable[i].EntryContext = &trackDriverForMiniDumpLog; 1522 paramTable[i].DefaultType = REG_DWORD; 1523 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 1524 paramTable[i].DefaultData = &defaultTrue; 1525 #else 1526 paramTable[i].DefaultData = &zero; 1527 #endif 1528 paramTable[i].DefaultLength = sizeof(ULONG); 1529 1530 requestParentOptimizationOn = (ULONG) TRUE; 1531 i++; 1532 1533 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1534 paramTable[i].Name = L"RequestParentOptimizationOn"; 1535 paramTable[i].EntryContext = &requestParentOptimizationOn; 1536 paramTable[i].DefaultType = REG_DWORD; 1537 paramTable[i].DefaultData = &defaultTrue; 1538 paramTable[i].DefaultLength = sizeof(ULONG); 1539 1540 dsfValue = 0; 1541 i++; 1542 1543 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1544 paramTable[i].Name = L"DsfOn"; 1545 paramTable[i].EntryContext = &dsfValue; 1546 paramTable[i].DefaultType = REG_DWORD; 1547 paramTable[i].DefaultData = &zero; 1548 paramTable[i].DefaultLength = sizeof(ULONG); 1549 1550 removeLockOptionFlags = 0; 1551 i++; 1552 1553 paramTable[i].Flags = RTL_QUERY_REGISTRY_DIRECT; 1554 paramTable[i].Name = L"RemoveLockOptionFlags"; 1555 paramTable[i].EntryContext = &removeLockOptionFlags; 1556 paramTable[i].DefaultType = REG_DWORD; 1557 paramTable[i].DefaultData = &zero; 1558 paramTable[i].DefaultLength = sizeof(ULONG); 1559 1560 ASSERT(i < sizeof(paramTable) / sizeof(paramTable[0])); 1561 1562 #if (FX_CORE_MODE==FX_CORE_USER_MODE) 1563 1564 queryFn = (QUERYFN*) GetProcAddress( 1565 GetModuleHandle(TEXT("ntdll.dll")), 1566 "RtlQueryRegistryValuesEx" 1567 ); 1568 1569 #else 1570 1571 RtlInitUnicodeString(&FunctionName, L"RtlQueryRegistryValuesEx"); 1572 1573 #pragma warning(push) 1574 #pragma warning(disable: 4055) 1575 1576 queryFn = (QUERYFN*)MmGetSystemRoutineAddress(&FunctionName); 1577 1578 #pragma warning(pop) 1579 1580 #endif 1581 1582 if (queryFn == NULL) { 1583 queryFn = &RtlQueryRegistryValues; 1584 } 1585 1586 status = queryFn( 1587 RTL_REGISTRY_OPTIONAL | RTL_REGISTRY_HANDLE, 1588 (PWSTR) hWdf.m_Key, 1589 ¶mTable[0], 1590 NULL, 1591 NULL 1592 ); 1593 1594 // 1595 // Only examine key values on success 1596 // 1597 if (NT_SUCCESS(status)) { 1598 1599 if (verboseValue) { 1600 FxDriverGlobals->FxVerboseOn = TRUE; 1601 } 1602 else { 1603 FxDriverGlobals->FxVerboseOn = FALSE; 1604 } 1605 1606 if (allocateFailValue != (ULONG) -1) { 1607 FxDriverGlobals->WdfVerifierAllocateFailCount = (LONG) allocateFailValue; 1608 } 1609 else { 1610 FxDriverGlobals->WdfVerifierAllocateFailCount = -1; 1611 } 1612 1613 // 1614 // Verifier settings are all or nothing. We currently do not support 1615 // turning on individual sub-verifiers. 1616 // 1617 FxDriverGlobals->SetVerifierState(verifierOnValue ? TRUE : FALSE); 1618 1619 if (FxDriverGlobals->FxVerifierOn) { 1620 FxDriverGlobalsInitializeDebugExtension(FxDriverGlobals, hWdf.m_Key); 1621 } 1622 1623 // 1624 // Update FxVerifyDownLevel independent of FxVerifyOn because for UMDF 1625 // verifer is always on so it does not consume FxVerifyOn value 1626 // 1627 if (verifyDownlevelValue) { 1628 FxDriverGlobals->FxVerifyDownlevel = TRUE; 1629 } 1630 else { 1631 FxDriverGlobals->FxVerifyDownlevel = FALSE; 1632 } 1633 1634 // 1635 // See if there exists an override in the registry for WDFVERIFY state. 1636 // We query for this separately so that we can establish a default state 1637 // based on verifierOnValue, and then know if the value was present in 1638 // the registry to override the default. 1639 // 1640 FxOverrideDefaultVerifierSettings(hWdf.m_Key, 1641 L"VerifyOn", 1642 &FxDriverGlobals->FxVerifyOn); 1643 1644 if (FxDriverGlobals->FxVerifyOn) { 1645 FxDriverGlobals->Public.DriverFlags |= WdfVerifyOn; 1646 } 1647 1648 FxOverrideDefaultVerifierSettings(hWdf.m_Key, 1649 L"DbgBreakOnError", 1650 &FxDriverGlobals->FxVerifierDbgBreakOnError); 1651 1652 FxOverrideDefaultVerifierSettings(hWdf.m_Key, 1653 L"DbgBreakOnDeviceStateError", 1654 &FxDriverGlobals->FxVerifierDbgBreakOnDeviceStateError); 1655 1656 if (FxDriverGlobals->FxVerifierDbgBreakOnError) { 1657 timeoutValue = 0; 1658 DECLARE_CONST_UNICODE_STRING(timeoutName, L"DbgWaitForSignalTimeoutInSec"); 1659 1660 // 1661 // Get the override value for the WaitForSignal's timeout if present. 1662 // 1663 if (NT_SUCCESS(FxRegKey::_QueryULong(hWdf.m_Key, 1664 &timeoutName, 1665 &timeoutValue))) { 1666 1667 FxDriverGlobals->FxVerifierDbgWaitForSignalTimeoutInSec = timeoutValue; 1668 } 1669 } 1670 1671 timeoutValue = 0; 1672 DECLARE_CONST_UNICODE_STRING(timeoutName, L"DbgWaitForWakeInterruptIsrTimeoutInSec"); 1673 1674 // 1675 // Get the override value for the Wake Interrupt ISR timeout if present. 1676 // Since the wake interrupt feature is only supported for 1.13 and higher, 1677 // avoid querying the reg key for older versions 1678 // 1679 if (FxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,13) && 1680 NT_SUCCESS(FxRegKey::_QueryULong(hWdf.m_Key, 1681 &timeoutName, 1682 &timeoutValue))) { 1683 1684 FxDriverGlobals->DbgWaitForWakeInterruptIsrTimeoutInSec = timeoutValue; 1685 } 1686 1687 FxDriverGlobals->FxForceLogsInMiniDump = 1688 (forceLogsInMiniDump) ? TRUE : FALSE; 1689 1690 FxDriverGlobals->FxTrackDriverForMiniDumpLog = 1691 (trackDriverForMiniDumpLog) ? TRUE : FALSE; 1692 1693 FxDriverGlobals->FxRequestParentOptimizationOn = 1694 (requestParentOptimizationOn) ? TRUE : FALSE; 1695 1696 FxDriverGlobals->FxDsfOn = (dsfValue) ? TRUE : FALSE; 1697 1698 FxDriverGlobals->RemoveLockOptionFlags = removeLockOptionFlags; 1699 } 1700 1701 return; 1702 } 1703 1704 VOID 1705 FX_DRIVER_GLOBALS::WaitForSignal( 1706 __in MxEvent* Event, 1707 __in PCSTR ReasonForWaiting, 1708 __in WDFOBJECT Handle, 1709 __in ULONG WarningTimeoutInSec, 1710 __in ULONG WaitSignalFlags 1711 ) 1712 { 1713 LARGE_INTEGER timeOut; 1714 NTSTATUS status; 1715 1716 ASSERT(Mx::MxGetCurrentIrql() == PASSIVE_LEVEL); 1717 1718 timeOut.QuadPart = WDF_REL_TIMEOUT_IN_SEC(((ULONGLONG)WarningTimeoutInSec)); 1719 1720 do { 1721 status = Event->WaitFor(Executive, 1722 KernelMode, 1723 FALSE, // Non alertable 1724 timeOut.QuadPart ? &timeOut : NULL); 1725 1726 if(status == STATUS_TIMEOUT) { 1727 DbgPrint("Thread 0x%p is %s 0x%p\n", 1728 Mx::MxGetCurrentThread(), 1729 ReasonForWaiting, 1730 Handle); 1731 1732 if ((WaitSignalFlags & WaitSignalAlwaysBreak) || 1733 ((WaitSignalFlags & WaitSignalBreakUnderVerifier) && 1734 FxVerifierDbgBreakOnError) || 1735 ((WaitSignalFlags & WaitSignalBreakUnderDebugger) && 1736 IsDebuggerAttached())) { 1737 1738 DbgBreakPoint(); 1739 } 1740 } else { 1741 ASSERT(NT_SUCCESS(status)); 1742 break; 1743 } 1744 } WHILE(TRUE); 1745 } 1746 1747 } // extern "C" 1748