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
FxVerifyObjectTypeInTable(__in USHORT ObjectType)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*
FxVerifyAllocateDebugInfo(__in LPWSTR HandleNameList,__in PFX_DRIVER_GLOBALS FxDriverGlobals)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
FxDriverGlobalsInitializeDebugExtension(__inout PFX_DRIVER_GLOBALS FxDriverGlobals,__in_opt HANDLE Key)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
FxObjectTypeToHandleName(__in WDFTYPE ObjectType)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
FxVerifierGetTrackReferences(__in FxObjectDebugInfo * DebugInfo,__in WDFTYPE ObjectType)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
FxVerifyObjectTableIsSorted(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
FxLibraryGlobalsVerifyVersion(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
FxLibraryGlobalsQueryRegistrySettings(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
FxLibraryGlobalsCommission(VOID)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
FxLibraryGlobalsDecommission(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
VerifierPageLockHandle(VOID)774 VerifierPageLockHandle (
775     VOID
776     )
777 {
778     PAGED_CODE_LOCKED();
779     DO_NOTHING();
780 }
781 
782 VOID
LockVerifierSection(_In_ PFX_DRIVER_GLOBALS FxDriverGlobals,_In_ PCUNICODE_STRING RegistryPath)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
UnlockVerifierSection(_In_ PFX_DRIVER_GLOBALS FxDriverGlobals)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
FxInitialize(__inout PFX_DRIVER_GLOBALS FxDriverGlobals,__in MdDriverObject DriverObject,__in PCUNICODE_STRING RegistryPath,__in_opt PWDF_DRIVER_CONFIG DriverConfig)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
IsWindowsVerifierOn(_In_ MdDriverObject DriverObject)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
FxDestroy(__in PFX_DRIVER_GLOBALS FxDriverGlobals)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
FxAllocateDriverGlobals(VOID)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
FxFreeDriverGlobals(__in PWDF_DRIVER_GLOBALS DriverGlobals)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*
FxVerifierGetObjectDebugInfo(__in HANDLE Key,__in PFX_DRIVER_GLOBALS FxDriverGlobals)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
FxVerifierQueryTrackPower(__in HANDLE Key,__out FxTrackPowerOption * TrackPower)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
FxOverrideDefaultVerifierSettings(__in HANDLE Key,__in LPWSTR Name,__out PBOOLEAN OverrideValue)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
FxRegistrySettingsInitialize(__inout PFX_DRIVER_GLOBALS FxDriverGlobals,__in PCUNICODE_STRING RegistryPath,__in BOOLEAN WindowsVerifierOn)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, &parametersPath, &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 (&paramTable[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         &paramTable[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
WaitForSignal(__in MxEvent * Event,__in PCSTR ReasonForWaiting,__in WDFOBJECT Handle,__in ULONG WarningTimeoutInSec,__in ULONG WaitSignalFlags)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