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, ¶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
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