ReactOS  0.4.15-dev-3193-g74513a7
fxbugcheckcallback.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation. All rights reserved.
4 
5 Module Name:
6 
7  FxBugcheckCallback.cpp
8 
9 Abstract:
10 
11  This module contains the bugcheck callback functions for determining whether
12  a wdf driver caused a bugcheck and for capturing the IFR data to the mini-
13  dump file.
14 
15 Revision History:
16 
17 
18 
19 --*/
20 
21 
22 #include "fxcorepch.hpp"
23 #include "fxifr.h"
24 #include "fxifrkm.h" // kernel mode only IFR definitions
25 #include "fxldr.h"
26 #include "fxbugcheck.h"
27 
28 #include <aux_klib.h>
29 
30 //
31 // Disable warnings of features used by the standard headers
32 //
33 // Disable warning C4115: named type definition in parentheses
34 // Disable warning C4200: nonstandard extension used : zero-sized array in struct/union
35 // Disable warning C4201: nonstandard extension used : nameless struct/union
36 // Disable warning C4214: nonstandard extension used : bit field types other than int
37 //
38 // #pragma warning(disable:4115 4200 4201 4214)
39 #include <ntimage.h>
40 // #pragma warning(default:4115 4200 4201 4214)
41 
42 
43 extern "C" {
44 
45 //
46 // Private methods.
47 //
49 BOOLEAN
52  __in PFX_DRIVER_GLOBALS FxDriverGlobals
53  );
54 
59  __out PVOID* ImageBase,
60  __out PULONG ImageSize
61  );
62 
64 BOOLEAN
66  __inout PFX_DRIVER_GLOBALS FxDriverGlobals
67  );
68 
69 KBUGCHECK_REASON_CALLBACK_ROUTINE FxpBugCheckCallback;
70 
71 KBUGCHECK_REASON_CALLBACK_ROUTINE FxpLibraryBugCheckCallback;
72 
74 BOOLEAN
77  __in PFX_DRIVER_GLOBALS FxDriverGlobals
78  )
79 /*++
80 
81 Routine Description:
82 
83  This routine will check the address to determine if it falls within the
84  image of a WDF component (Library, Client driver or Class Extension).
85  This is accomplished by traversing the WdfLdrGlobals.LoadedModuleList
86  and comparing each image start/end address with Address.
87 
88 Arguments:
89 
90  PVOID Address - The address to be checked, and it need not be currently
91  paged in. In other words, it is NOT used in this routine as an
92  address, but more as a simple scaler into a 4GB (x86) array.
93 
94  NOTE - Do not attempt to validatate Address, say via MmIsAddressValid(Address).
95  Address's memory could be paged out, but Address is still valid.
96 
97  PFX_DRIVER_GLOBALS FxDriverGlobals - Driver's globals.
98 
99 Return Value:
100 
101  TRUE indicates something was found, either library, client or both.
102  FALSE indicates either not found or invalid parameters.
103 
104 --*/
105 {
106 
107  if (NULL == Address || NULL == FxDriverGlobals) {
108  return FALSE;
109  }
110 
111  if (Address >= FxDriverGlobals->ImageAddress &&
112  Address < WDF_PTR_ADD_OFFSET(FxDriverGlobals->ImageAddress,
113  FxDriverGlobals->ImageSize)) {
114  return TRUE;
115  }
116 
117  return FALSE;
118 }
119 
121 NTSTATUS
124  __out PVOID* ImageBase,
125  __out PULONG ImageSize
126  )
127 {
129  ULONG modulesSize = 0;
130  AUX_MODULE_EXTENDED_INFO* modules = NULL;
132  PVOID addressInImage = NULL;
133  ULONG numberOfModules;
134  ULONG i;
135 
136  //
137  // Basic validation.
138  //
139  if (NULL == DriverObject || NULL == ImageBase || NULL == ImageSize) {
141  goto exit;
142  }
143 
144  //
145  // Get the address of a well known entry in the Image.
146  //
147  addressInImage = (PVOID) DriverObject->DriverStart;
148  ASSERT(addressInImage != NULL);
149 
150  //
151  // Initialize the AUX Kernel Library.
152  //
154  if (!NT_SUCCESS(status)) {
155  goto exit;
156  }
157 
158  //
159  // Get size of area needed for loaded modules.
160  //
161  status = AuxKlibQueryModuleInformation(&modulesSize,
162  sizeof(AUX_MODULE_EXTENDED_INFO),
163  NULL);
164 
165  if (!NT_SUCCESS(status) || (0 == modulesSize)) {
166  goto exit;
167  }
168 
169  numberOfModules = modulesSize / sizeof(AUX_MODULE_EXTENDED_INFO);
170 
171  //
172  // Allocate returned-sized memory for the modules area.
173  //
175  modulesSize,
176  '30LW');
177  if (NULL == modules) {
179  goto exit;
180  }
181 
182  //
183  // Request the modules array be filled with module information.
184  //
185  status = AuxKlibQueryModuleInformation(&modulesSize,
186  sizeof(AUX_MODULE_EXTENDED_INFO),
187  modules);
188 
189  if (!NT_SUCCESS(status)) {
190  goto exit;
191  }
192 
193  //
194  // Traverse list, searching for the well known address in Image for which the
195  // module's Image Base Address is in its range.
196  //
197  module = modules;
198 
199  for (i=0; i < numberOfModules; i++) {
200 
201  if (addressInImage >= module->BasicInfo.ImageBase &&
202  addressInImage < WDF_PTR_ADD_OFFSET(module->BasicInfo.ImageBase,
203  module->ImageSize)) {
204 
205  *ImageBase = module->BasicInfo.ImageBase;
206  *ImageSize = module->ImageSize;
207 
209  goto exit;
210  }
211  module++;
212  }
213 
215 
216 exit:
217 
218  if (modules != NULL) {
219  ExFreePool(modules);
220  modules = NULL;
221  }
222 
223  return status;
224 }
225 
227 BOOLEAN
229  __inout PFX_DRIVER_GLOBALS FxDriverGlobals
230  )
231 /*++
232 
233 Routine Description:
234 
235  This routine evaluates whether the driver's IFR data has to be written to
236  the mini-dump file.
237 
238 Arguments:
239 
240  FxDriverGlobals - The driver globals of the wdf driver.
241 
242 Return Value:
243 
244  TRUE - Indicates this driver's IFR log is to be captured in dump.
245  FALSE - Indicates this driver's log is (probably) not of interest.
246 
247 --*/
248 {
249  PVOID codeAddr = NULL;
250  BOOLEAN found = FALSE;
251  KBUGCHECK_DATA bugCheckData = {0};
252 
253  if (FxDriverGlobals->FxForceLogsInMiniDump) {
254  return TRUE;
255  }
256 
257  //
258  // Retrieve the bugcheck parameters.
259  //
260  bugCheckData.BugCheckDataSize = sizeof(KBUGCHECK_DATA);
261  AuxKlibGetBugCheckData(&bugCheckData);
262 
263  //
264  // Check whether the code address that caused the bugcheck is from this wdf
265  // driver.
266  //
267  switch (bugCheckData.BugCheckCode) {
268 
269  case KERNEL_APC_PENDING_DURING_EXIT: // 0x20
270  codeAddr = (PVOID)bugCheckData.Parameter1;
271  found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals);
272  break;
273 
274  case KMODE_EXCEPTION_NOT_HANDLED: // 0x1E
275  case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED: // 0x7E
276  case KERNEL_MODE_EXCEPTION_NOT_HANDLED: // 0x8E
277  codeAddr = (PVOID)bugCheckData.Parameter2;
278  found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals);
279  break;
280 
281  case PAGE_FAULT_IN_NONPAGED_AREA: // 0x50
282  codeAddr = (PVOID)bugCheckData.Parameter3;
283  found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals);
284  break;
285 
286  case IRQL_NOT_LESS_OR_EQUAL: // 0xA
287  case DRIVER_IRQL_NOT_LESS_OR_EQUAL: // 0xD1
288  codeAddr = (PVOID)bugCheckData.Parameter4;
289  found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals);
290  break;
291  }
292 
293  //
294  // If the code address was found in the wdf driver, then set the flag in the
295  // driver globals to indicate that the IFR data has to be written to the
296  // mini-dump.
297  //
298  if (found) {
299  FxDriverGlobals->FxForceLogsInMiniDump = TRUE;
300  }
301  return found;
302 }
303 
304 VOID
305 STDCALL
310  __in ULONG ReasonSpecificLength
311  )
312 
313 /*++
314 
315 Routine Description:
316 
317  BugCheck callback routine for WDF
318 
319 Arguments:
320 
321  Reason - Must be KbCallbackSecondaryData
322  Record - Supplies the bugcheck record previously registered
323  ReasonSpecificData - Pointer to KBUGCHECK_SECONDARY_DUMP_DATA
324  ReasonSpecificLength - Sizeof(ReasonSpecificData)
325 
326 Return Value:
327 
328  None
329 
330 Notes:
331  When a bugcheck happens the kernel bugcheck processor will make two passes
332  of all registered BugCheckCallbackRecord routines. The first pass, called
333  the "sizing pass" essentially queries all the callbacks to collect the
334  total size of the secondary dump data. In the second pass the actual data
335  is captured to the dump.
336 
337 --*/
338 
339 {
342  ULONG logSize;
343  BOOLEAN writeLog = FALSE;
344 
346  UNREFERENCED_PARAMETER(ReasonSpecificLength);
347 
348  ASSERT(ReasonSpecificLength >= sizeof(KBUGCHECK_SECONDARY_DUMP_DATA));
349  ASSERT(Reason == KbCallbackSecondaryDumpData);
350 
352 
353  //
354  // See if the IFR's minimum amount of data can fit in the dump
355  //
356  if (dumpData->MaximumAllowed < FxIFRMinLogSize) {
357  return;
358  }
359 
360  //
361  // Get the driver globals containing the bugcheck callback record.
362  //
365  BugCheckCallbackRecord);
366 
367  //
368  // If there is not IFR data, then this bugcheck callback does not have any
369  // data to write to the minidump.
370  //
372  return;
373  }
374 
375  //
376  // Size is the length of the buffer which we log to. It should also include
377  // the size of the header (which was subtracted out in FxIFRStart).
378  //
379  logSize = ((PWDF_IFR_HEADER) fxDriverGlobals->WdfLogHeader)->Size +
380  sizeof(WDF_IFR_HEADER);
381 
382  ASSERT(FxIFRMinLogSize <= logSize && logSize <= FxIFRMaxLogSize);
383 
384  //
385  // Check whether log can fit in the dump.
386  //
387  if (logSize > dumpData->MaximumAllowed) {
388  return;
389  }
390 
391  //
392  // Check whether this log is the one to copy.
393  //
395  //
396  // Let everyone know that we got the best match.
397  //
399 
400  //
401  // Exact match driver.
402  //
403  writeLog = TRUE;
404  }
406  //
407  // So far we didn't get a perfect match. Make a best effort
408  // to find a good candidate for the driver dump log.
409  //
412  fxDriverGlobals) {
413  //
414  // Best effort match driver.
415  //
416  writeLog = TRUE;
417  }
418  }
419 
420  if (writeLog) {
422  dumpData->OutBufferLength = logSize;
423  dumpData->Guid = WdfDumpGuid;
424  }
425 }
426 
427 VOID
429  __inout PFX_DRIVER_GLOBALS FxDriverGlobals,
431  )
432 {
433  UNICODE_STRING funcName;
434  PKBUGCHECK_REASON_CALLBACK_RECORD callbackRecord;
436  BOOLEAN enableDriverTracking;
437 
438  //
439  // If any problem during this setup, disable driver tracking.
440  //
441  enableDriverTracking = FxDriverGlobals->FxTrackDriverForMiniDumpLog;
442  FxDriverGlobals->FxTrackDriverForMiniDumpLog = FALSE;
443 
444  //
445  // Zero out callback record.
446  //
447  callbackRecord = &FxDriverGlobals->BugCheckCallbackRecord;
448  RtlZeroMemory(callbackRecord, sizeof(KBUGCHECK_REASON_CALLBACK_RECORD));
449 
450  //
451  // Get the Image base address and size before registering the bugcheck
452  // callbacks. If the image base address and size cannot be computed,
453  // then the bugcheck callbacks depend on these values being properly
454  // set.
455  //
456  FxDriverGlobals->ImageAddress = NULL;
457  FxDriverGlobals->ImageSize = 0;
458 
460  &FxDriverGlobals->ImageAddress,
461  &FxDriverGlobals->ImageSize))) {
462  goto Done;
463  }
464 
465 
466 
467 
468 
469 
470 
471 
472 
473 
474  //
475  // The KeRegisterBugCheckReasonCallback exists for xp sp1 and above. So
476  // check whether this function is defined on the current OS and register
477  // for the bugcheck callback only if this function is defined.
478  //
479  RtlInitUnicodeString(&funcName, L"KeRegisterBugCheckReasonCallback");
481  MmGetSystemRoutineAddress(&funcName);
482 
483  if (NULL == funcPtr) {
484  goto Done;
485  }
486 
487  //
488  // Register this driver with driver tracker.
489  //
490  if (enableDriverTracking) {
492  FxDriverGlobals))) {
493  FxDriverGlobals->FxTrackDriverForMiniDumpLog = TRUE;
494  }
495  }
496 
497  //
498  // Initialize the callback record.
499  //
500  KeInitializeCallbackRecord(callbackRecord);
501 
502  //
503  // Register the bugcheck callback.
504  //
505  funcPtr(callbackRecord,
507  KbCallbackSecondaryDumpData,
508  (PUCHAR)FxDriverGlobals->Public.DriverName);
509 
510  ASSERT(callbackRecord->CallbackRoutine != NULL);
511 
512 Done:;
513 }
514 
515 VOID
517  __inout PFX_DRIVER_GLOBALS FxDriverGlobals
518  )
519 {
520  UNICODE_STRING funcName;
521  PKBUGCHECK_REASON_CALLBACK_RECORD callbackRecord;
523 
524  callbackRecord = &FxDriverGlobals->BugCheckCallbackRecord;
525  if (NULL == callbackRecord->CallbackRoutine) {
526  goto Done;
527  }
528 
529  //
530  // The KeDeregisterBugCheckReasonCallback exists for xp sp1 and above. So
531  // check whether this function is defined on the current OS and deregister
532  // from the bugcheck callback only if this function is defined.
533  //
534  RtlInitUnicodeString(&funcName, L"KeDeregisterBugCheckReasonCallback");
536  MmGetSystemRoutineAddress(&funcName);
537 
538  if (NULL == funcPtr) {
539  goto Done;
540  }
541 
542  funcPtr(callbackRecord);
543  callbackRecord->CallbackRoutine = NULL;
544 
545  //
546  // Deregister this driver with driver tracker.
547  //
548  if (FxDriverGlobals->FxTrackDriverForMiniDumpLog) {
549  FxLibraryGlobals.DriverTracker.Deregister(FxDriverGlobals);
550  }
551 
552 Done:;
553 }
554 
555 VOID
556 STDCALL
561  __in ULONG ReasonSpecificLength
562  )
563 
564 /*++
565 
566 Routine Description:
567 
568  Global (framework-library) BugCheck callback routine for WDF
569 
570 Arguments:
571 
572  Reason - Must be KbCallbackSecondaryData
573  Record - Supplies the bugcheck record previously registered
574  ReasonSpecificData - Pointer to KBUGCHECK_SECONDARY_DUMP_DATA
575  ReasonSpecificLength - Sizeof(ReasonSpecificData)
576 
577 Return Value:
578 
579  None
580 
581 Notes:
582  When a bugcheck happens the kernel bugcheck processor will make two passes
583  of all registered BugCheckCallbackRecord routines. The first pass, called
584  the "sizing pass" essentially queries all the callbacks to collect the
585  total size of the secondary dump data. In the second pass the actual data
586  is captured to the dump.
587 
588 --*/
589 
590 {
592  ULONG dumpSize;
593 
595  UNREFERENCED_PARAMETER(ReasonSpecificLength);
596 
597  ASSERT(ReasonSpecificLength >= sizeof(KBUGCHECK_SECONDARY_DUMP_DATA));
598  ASSERT(Reason == KbCallbackSecondaryDumpData);
599 
603  //
604  // See if the bugcheck driver info is more than can fit in the dump
605  //
606  if (dumpData->MaximumAllowed < dumpSize) {
607  dumpSize = EXP_ALIGN_DOWN_ON_BOUNDARY(
608  dumpData->MaximumAllowed,
609  sizeof(FX_DUMP_DRIVER_INFO_ENTRY));
610  }
611 
612  if (0 == dumpSize) {
613  goto Done;
614  }
615 
616  //
617  // Ok, provide the info about the bugcheck data.
618  //
620  dumpData->OutBufferLength = dumpSize;
621  dumpData->Guid = WdfDumpGuid2;
622 
623 Done:;
624 }
625 
626 VOID
628 {
630  UNICODE_STRING funcName;
631  PKBUGCHECK_REASON_CALLBACK_RECORD callbackRecord;
633  SIZE_T arraySize;
634  ULONG arrayCount;
635 
636 
637  callbackRecord = &FxLibraryGlobals.BugCheckCallbackRecord;
638  RtlZeroMemory(callbackRecord, sizeof(KBUGCHECK_REASON_CALLBACK_RECORD));
639 
643 
644 
645 
646 
647 
648 
649 
650 
651 
652 
653  //
654  // The KeRegisterBugCheckReasonCallback exists for xp sp1 and above. So
655  // check whether this function is defined on the current OS and register
656  // for the bugcheck callback only if this function is defined.
657  //
658  RtlInitUnicodeString(&funcName, L"KeRegisterBugCheckReasonCallback");
660  MmGetSystemRoutineAddress(&funcName);
661 
662  if (NULL == funcPtr) {
663  goto Done;
664  }
665 
667  arrayCount = FX_DUMP_DRIVER_INFO_INCREMENT;
668 
671  NonPagedPool,
672  arraySize,
673  FX_TAG);
674 
676  goto Done;
677  }
678 
680 
681  //
682  // Init first entry for the framework.
683  //
685  FxLibraryGlobals.BugCheckDriverInfo[0].Version.Major = __WDF_MAJOR_VERSION;
686  FxLibraryGlobals.BugCheckDriverInfo[0].Version.Minor = __WDF_MINOR_VERSION;
687  FxLibraryGlobals.BugCheckDriverInfo[0].Version.Build = __WDF_BUILD_NUMBER;
688 
692  WdfLdrType);
693 
694  if (!NT_SUCCESS(status)) {
695  ASSERT(FALSE);
697  }
698 
700 
701  //
702  // Initialize the callback record.
703  //
704  KeInitializeCallbackRecord(callbackRecord);
705 
706  //
707  // Register the bugcheck callback.
708  //
709  funcPtr(callbackRecord,
711  KbCallbackSecondaryDumpData,
712  (PUCHAR)WdfLdrType);
713 
714  ASSERT(callbackRecord->CallbackRoutine != NULL);
715 
716 Done:;
717 }
718 
719 VOID
721 {
722  UNICODE_STRING funcName;
723  PKBUGCHECK_REASON_CALLBACK_RECORD callbackRecord;
725 
726  //
727  // Deregister callback.
728  //
729 
730 
731 
732 
733 
734 
735 
736  callbackRecord = &FxLibraryGlobals.BugCheckCallbackRecord;
737  if (NULL == callbackRecord->CallbackRoutine) {
738  goto Done;
739  }
740 
741  //
742  // The KeDeregisterBugCheckReasonCallback exists for xp sp1 and above. So
743  // check whether this function is defined on the current OS and deregister
744  // from the bugcheck callback only if this function is defined.
745  //
746  RtlInitUnicodeString(&funcName, L"KeDeregisterBugCheckReasonCallback");
748  MmGetSystemRoutineAddress(&funcName);
749 
750  if (NULL == funcPtr) {
751  goto Done;
752  }
753 
754  funcPtr(callbackRecord);
755  callbackRecord->CallbackRoutine = NULL;
756 
757  //
758  // Release memory.
759  //
761  goto Done;
762  }
763 
764  //
765  // Dynamic KMDF framework is unloading, make sure there is only one entry
766  // left in the driver info array; the framework lib was using this entry
767  // to store its version.
768  //
770 
773 
776 
777 Done:;
778 }
779 
780 VOID
782  __in PFX_DRIVER_GLOBALS FxDriverGlobals
783  )
784 {
785  KIRQL irql;
786  PFX_DUMP_DRIVER_INFO_ENTRY driverInfo = NULL;
787  PFX_DUMP_DRIVER_INFO_ENTRY oldDriverInfo = NULL;
788  ULONG newCount = 0;
789 
790  //
791  // Clear driver index (0-based). Drivers do not use index 0.
792  //
793  FxDriverGlobals->BugCheckDriverInfoIndex = 0;
794 
796  return;
797  }
798 
800 
801  //
802  // Make sure we have enough space, else allocate some more memory.
803  //
806 
807  //
808  // Just exit if no more space in dump buffer.
809  //
812  ASSERT(FALSE);
813  goto Done;
814  }
815 
818 
819  //
820  // Allocate new buffer to hold driver info.
821  //
823  NonPagedPool,
824  sizeof(FX_DUMP_DRIVER_INFO_ENTRY)* newCount,
825  FX_TAG);
826 
827  if (NULL == driverInfo) {
828  goto Done;
829  }
830 
831  //
832  // Copy data from old to new buffer.
833  //
834  RtlCopyMemory(driverInfo,
837  sizeof(FX_DUMP_DRIVER_INFO_ENTRY));
838  //
839  // Ok, replace global pointer and its count.
840  //
841  oldDriverInfo = FxLibraryGlobals.BugCheckDriverInfo;
844  driverInfo = NULL; // just in case.
845 
846  //
847  // Free old memory.
848  //
849  MxMemory::MxFreePool(oldDriverInfo);
850  oldDriverInfo = NULL;
851  }
852 
855  //
856  // Compute ptr to free entry.
857  //
858  driverInfo = FxLibraryGlobals.BugCheckDriverInfo +
860  //
861  // Cache some of this driver's info.
862  //
863  driverInfo->FxDriverGlobals = FxDriverGlobals;
864  driverInfo->Version = FxDriverGlobals->WdfBindInfo->Version;
865 
866  C_ASSERT(sizeof(driverInfo->DriverName) ==
867  sizeof(FxDriverGlobals->Public.DriverName));
868  RtlCopyMemory(driverInfo->DriverName,
869  FxDriverGlobals->Public.DriverName,
870  sizeof(driverInfo->DriverName));
871  driverInfo->DriverName[ARRAY_SIZE(driverInfo->DriverName) - 1] = '\0';
872 
873  //
874  // Cache this index for later when the driver is removed.
875  //
876  FxDriverGlobals->BugCheckDriverInfoIndex =
878 
879  //
880  // Update global index.
881  //
883 
884 Done:
885 
887 }
888 
889 VOID
891  __in PFX_DRIVER_GLOBALS FxDriverGlobals
892  )
893 {
894  KIRQL irql;
895  PFX_DUMP_DRIVER_INFO_ENTRY driverInfo = NULL;
896  ULONG driverIndex = 0;
897  ULONG shiftCount = 0;
898  ULONG i = 0;
899 
901 
902  //
903  // Zero means 'not used'.
904  //
905  driverIndex = FxDriverGlobals->BugCheckDriverInfoIndex;
906  if (0 == driverIndex) {
907  goto Done;
908  }
909 
910  //
911  // Check if feature is not supported.
912  //
914  ASSERT(FALSE); // driverIndex > 0 with NULL array?
915  goto Done;
916  }
917 
918 
921 
922  //
923  // Index boundary validation.
924  //
925  if (driverIndex >= FxLibraryGlobals.BugCheckDriverInfoIndex) {
926  ASSERT(FALSE);
927  goto Done;
928  }
929 
930  //
931  // Compute ptr to driver info.
932  //
933  driverInfo = FxLibraryGlobals.BugCheckDriverInfo + driverIndex;
934 
935  //
936  // Double-check that this is the same driver.
937  //
938  if (driverInfo->FxDriverGlobals != FxDriverGlobals) {
939  ASSERT(FALSE);
940  goto Done;
941  }
942 
943  //
944  // Shift memory to fill hole and update global free index.
945  //
946  shiftCount = FxLibraryGlobals.BugCheckDriverInfoIndex - driverIndex - 1;
947  if (shiftCount > 0) {
948  RtlMoveMemory(driverInfo,
949  driverInfo + 1,
950  shiftCount * sizeof(FX_DUMP_DRIVER_INFO_ENTRY));
951  }
952 
954 
955  //
956  // Update cached index for all 'shifted' drivers.
957  //
958  for (i = driverIndex; i < FxLibraryGlobals.BugCheckDriverInfoIndex; ++i) {
960  BugCheckDriverInfoIndex--;
961  }
962 
963 Done:
964 
966 }
967 
968 //
969 // Driver usage tracker functions
970 //
971 NTSTATUS
973 {
974  //
975  // Global initialization. It balances the global Uninitialize function.
976  // The real init is actually done by the Register function the first time
977  // a driver registers with the device tracker.
978  //
980  m_PoolToFree = NULL;
981  m_EntrySize = 0;
982  m_Number = 0;
983 
984  return STATUS_SUCCESS;
985 }
986 
987 VOID
989 {
990  if (m_PoolToFree != NULL) {
991 
992 #ifdef DBG
993  for (ULONG index = 0; index < m_Number; ++index) {
994  PFX_DRIVER_TRACKER_ENTRY driverUsage = NULL;
995  driverUsage = GetProcessorDriverEntryRef(index);
996  ASSERT(NULL == driverUsage->FxDriverGlobals);
997  }
998 #endif
1000  m_PoolToFree = NULL;
1001  }
1002 
1003  m_DriverUsage = NULL;
1004  m_Number = 0;
1005 }
1006 
1007 NTSTATUS
1009  __in PFX_DRIVER_GLOBALS /* FxDriverGlobals */
1010  )
1011 {
1013  ULONG paddedSize = 0;
1014  ULONG index = 0;
1016  PFX_DRIVER_TRACKER_ENTRY driverUsage = NULL;
1017  UNICODE_STRING funcName;
1018  PVOID funcPtr = NULL;
1019 
1020  //
1021  // Nothing to do if tracker is already initialized. No need for a lock
1022  // here since PnP already serializes driver initialization.
1023  //
1024  if (m_PoolToFree != NULL) {
1025  ASSERT(m_DriverUsage != NULL && m_Number != 0);
1027  goto Done;
1028  }
1029 
1030  //
1031  // Intialize the procgrp down level library.
1032  //
1033  // WdmlibProcgrpInitialize(); __REACTOS__ : haha we don't support ProcGrp
1034 
1035  //
1036  // Capture maximum number of processors.
1037  //
1038  RtlInitUnicodeString(&funcName, L"KeQueryMaximumProcessorCountEx");
1039  funcPtr = MmGetSystemRoutineAddress(&funcName);
1040  if (funcPtr != NULL) {
1041  //
1042  // Win 7 and forward.
1043  //
1046  }
1047  else {
1048  RtlInitUnicodeString(&funcName, L"KeQueryMaximumProcessorCount");
1049  funcPtr = MmGetSystemRoutineAddress(&funcName);
1050  if (funcPtr != NULL) {
1051  //
1052  // Windows Server 2008.
1053  //
1055  }
1056  else {
1061  //
1062  // XP (Major=5, Minor>0) and Vista (Major=6, Minor=0).
1063  //
1064  m_Number = (ULONG)(*((CCHAR *)&KeNumberProcessors));
1065  }
1066  else {
1067  //
1068  // This feature is not supported for Windows 2000.
1069  //
1070  ASSERT(FALSE);
1072  goto Done;
1073  }
1074  }
1075  }
1076 
1077  //
1078  // Validate upper bound.
1079  //
1082  goto Done;
1083  }
1084 
1085  //
1086  // Determine padded size of each tracking entry structure.
1087  //
1088  if (m_Number > 1 ) {
1089  RtlInitUnicodeString(&funcName, L"KeGetRecommendedSharedDataAlignment");
1090  funcPtr = MmGetSystemRoutineAddress(&funcName);
1091 
1092  if (funcPtr != NULL) {
1093  //
1094  //XP and forward
1095  //
1096  paddedSize = ((PFN_KE_GET_RECOMMENDED_SHARED_DATA_ALIGNMENT)funcPtr)();
1097  ASSERT ((paddedSize & (paddedSize - 1)) == 0);
1098  }
1099  else {
1100  //
1101  // This feature is not supported for Windows 2000.
1102  //
1104  goto Done;
1105  }
1106  }
1107  else {
1108  paddedSize = sizeof(FX_DRIVER_TRACKER_ENTRY);
1109  }
1110 
1111  ASSERT(sizeof(FX_DRIVER_TRACKER_ENTRY) <= paddedSize);
1112 
1113  //
1114  // Remember the size.
1115  //
1116  m_EntrySize = paddedSize;
1117 
1119  NonPagedPool,
1120  paddedSize * m_Number,
1121  FX_TAG);
1122  if (NULL == pool) {
1124  goto Done;
1125  }
1126 
1127  //
1128  // Check if pool is aligned if this is a multi-proc.
1129  //
1130  if ((m_Number > 1) && !EXP_IS_PTR_ALIGNED_ON_BOUNDARY(pool, paddedSize)) {
1131  //
1132  // We will allocate a padded size, free the old pool.
1133  //
1134  ExFreePool(pool);
1135 
1136  //
1137  // Allocate enough padding so we can start the refs on an aligned boundary
1138  //
1140  NonPagedPool,
1141  paddedSize * m_Number + paddedSize,
1142  FX_TAG);
1143  if (NULL == pool) {
1145  goto Done;
1146  }
1147 
1148  driverUsage = (PFX_DRIVER_TRACKER_ENTRY)
1149  EXP_ALIGN_UP_PTR_ON_BOUNDARY(pool, paddedSize);
1150 
1151  }
1152  else {
1153  //
1154  // Already aligned pool.
1155  //
1156  driverUsage = pool;
1157  }
1158 
1159  //
1160  // Remember the pool block to free.
1161  //
1162  m_PoolToFree = pool;
1163  m_DriverUsage = driverUsage;
1164 
1165  //
1166  // Init driver usage entries.
1167  //
1168  for (index = 0; index < m_Number; ++index) {
1169  driverUsage = GetProcessorDriverEntryRef(index);
1170  driverUsage->FxDriverGlobals = NULL;
1171  }
1172 
1173  //
1174  // All done.
1175  //
1177 
1178 Done:
1179  return status;
1180 }
1181 
1182 VOID
1184  __in PFX_DRIVER_GLOBALS FxDriverGlobals
1185  )
1186 {
1187  ULONG index = 0;
1188  PFX_DRIVER_TRACKER_ENTRY driverUsage = NULL;
1189 
1190  //
1191  // Cleanup any refs to this driver's globals.
1192  //
1193  if (m_PoolToFree != NULL) {
1194 
1195  ASSERT(m_DriverUsage != NULL && m_Number != 0);
1196 
1197  for (index = 0; index < m_Number; ++index) {
1198  driverUsage = GetProcessorDriverEntryRef(index);
1199  if (driverUsage->FxDriverGlobals == FxDriverGlobals) {
1200  driverUsage->FxDriverGlobals = NULL;
1201  }
1202  }
1203  }
1204 }
1205 
1206 } // extern "C"
NTSTATUS NTAPI AuxKlibInitialize(VOID)
Definition: aux_klib.c:26
volatile PFX_DRIVER_GLOBALS FxDriverGlobals
Definition: fxglobalskm.h:354
BOOLEAN FxTrackDriverForMiniDumpLog
Definition: fxglobals.h:483
ULONG BugCheckDataSize
Definition: aux_klib.h:45
return STATUS_NOT_SUPPORTED
PFX_DRIVER_TRACKER_ENTRY m_DriverUsage
Definition: fxglobalskm.h:442
HMODULE module
Definition: main.cpp:47
_Must_inspect_result_ BOOLEAN FxpBugCheckCallbackFilter(__inout PFX_DRIVER_GLOBALS FxDriverGlobals)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
ULONG(STDCALL * PFN_KE_QUERY_MAXIMUM_PROCESSOR_COUNT)(VOID)
Definition: fxglobalskm.h:210
PFX_DRIVER_GLOBALS BestDriverForDumpLog
Definition: fxglobals.h:817
#define WDF_PTR_ADD_OFFSET(_ptr, _offset)
Definition: wdfcore.h:144
ULONG dwMinorVersion
Definition: rtltypes.h:271
BOOLEAN(STDCALL * PFN_KE_REGISTER_BUGCHECK_REASON_CALLBACK)(__in PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord, __in PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine, __in KBUGCHECK_CALLBACK_REASON Reason, __in PUCHAR Component)
Definition: fxglobalskm.h:83
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS NTAPI AuxKlibQueryModuleInformation(_In_ PULONG InformationLength, _In_ ULONG SizePerModule, _Inout_ PAUX_MODULE_EXTENDED_INFO ModuleInfo)
Definition: aux_klib.c:53
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
#define KeInitializeCallbackRecord(CallbackRecord)
Definition: kefuncs.h:1399
struct _KBUGCHECK_DATA KBUGCHECK_DATA
KIRQL irql
Definition: wave.h:1
PFX_DUMP_DRIVER_INFO_ENTRY BugCheckDriverInfo
Definition: fxglobals.h:791
ULONG BugCheckDriverInfoCount
Definition: fxglobals.h:785
VOID FxInitializeBugCheckDriverInfo()
VOID Deregister(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
RTL_OSVERSIONINFOEXW OsVersionInfo
Definition: fxglobals.h:770
ULONG(STDCALL * PFN_KE_GET_RECOMMENDED_SHARED_DATA_ALIGNMENT)(VOID)
Definition: fxglobalskm.h:222
Definition: fxbugcheck.h:81
struct _WDF_IFR_HEADER WDF_IFR_HEADER
VOID FxPurgeBugCheckDriverInfo(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
__inline PFX_DRIVER_TRACKER_ENTRY GetProcessorDriverEntryRef(__in ULONG Index)
Definition: fxglobalskm.h:427
ULONG dwMajorVersion
Definition: rtltypes.h:270
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:156
static __inline VOID MxFreePool(__in PVOID Ptr)
Definition: mxmemorykm.h:41
FX_DRIVER_TRACKER_CACHE_AWARE DriverTracker
Definition: fxglobals.h:812
struct _FX_DUMP_DRIVER_INFO_ENTRY * PFX_DUMP_DRIVER_INFO_ENTRY
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD * Record
Definition: ketypes.h:256
WDF_BUILD_NUMBER Build
Definition: fxldr.h:124
#define FALSE
Definition: types.h:117
PVOID NTAPI MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
Definition: sysldr.c:3514
static __inline PVOID MxAllocatePoolWithTag(__in POOL_TYPE PoolType, __in SIZE_T NumberOfBytes, __in ULONG Tag)
Definition: mxmemorykm.h:30
#define FX_DRIVER_TRACKER_MAX_CPUS
Definition: fxbugcheck.h:62
_Must_inspect_result_ BOOLEAN FxpIsAddressKnownToWdf(__in PVOID Address, __in PFX_DRIVER_GLOBALS FxDriverGlobals)
BOOLEAN(STDCALL * PFN_KE_DEREGISTER_BUGCHECK_REASON_CALLBACK)(__in PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecords)
Definition: fxglobalskm.h:92
#define __out
Definition: dbghelp.h:62
unsigned char BOOLEAN
#define FX_TAG
Definition: fxmacros.hpp:155
PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine
Definition: ketypes.h:299
static WCHAR Address[46]
Definition: ping.c:68
#define FX_DUMP_DRIVER_INFO_INCREMENT
Definition: fxbugcheck.h:67
#define C_ASSERT(e)
Definition: intsafe.h:73
GLuint index
Definition: glext.h:6031
void * PVOID
Definition: retypes.h:9
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _FX_DUMP_DRIVER_INFO_ENTRY FX_DUMP_DRIVER_INFO_ENTRY
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
VOID FxCacheBugCheckDriverInfo(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
#define STATUS_NOT_FOUND
Definition: shellext.h:72
struct _WDF_IFR_HEADER * PWDF_IFR_HEADER
#define STDCALL
Definition: wdf.h:45
#define ASSERT(a)
Definition: mode.c:44
struct _AUX_MODULE_EXTENDED_INFO AUX_MODULE_EXTENDED_INFO
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
char CCHAR
Definition: typedefs.h:51
VOID FxUninitializeBugCheckDriverInfo()
KBUGCHECK_REASON_CALLBACK_ROUTINE FxpBugCheckCallback
CHAR DriverName[WDF_DRIVER_GLOBALS_NAME_LEN]
Definition: fxbugcheck.h:84
WDF_MAJOR_VERSION Major
Definition: fxldr.h:122
ULONG(STDCALL * PFN_KE_QUERY_MAXIMUM_PROCESSOR_COUNT_EX)(__in USHORT GroupNumber)
Definition: fxglobalskm.h:204
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
ULONG_PTR Parameter4
Definition: aux_klib.h:50
#define index(s, c)
Definition: various.h:29
static const WCHAR L[]
Definition: oid.c:1250
_Must_inspect_result_ NTSTATUS Initialize()
#define EXP_ALIGN_DOWN_ON_BOUNDARY(_size, _alignment)
Definition: fxbugcheck.h:46
WDF_VERSION Version
Definition: fxbugcheck.h:83
#define __inout
Definition: dbghelp.h:50
_Must_inspect_result_ __inline PFX_DRIVER_GLOBALS GetCurrentTrackedDriver()
Definition: fxglobalskm.h:405
VOID FxRegisterBugCheckCallback(__inout PFX_DRIVER_GLOBALS FxDriverGlobals, __in PDRIVER_OBJECT DriverObject)
#define _Must_inspect_result_
Definition: ms_sal.h:558
FxLibraryGlobalsType FxLibraryGlobals
Definition: globals.cpp:95
ULONG_PTR Parameter1
Definition: aux_klib.h:47
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
ULONG_PTR Parameter3
Definition: aux_klib.h:49
ULONG BugCheckDriverInfoIndex
Definition: fxglobals.h:780
ULONG_PTR Parameter2
Definition: aux_klib.h:48
ULONG_PTR SIZE_T
Definition: typedefs.h:80
KBUGCHECK_REASON_CALLBACK_ROUTINE FxpLibraryBugCheckCallback
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ARRAY_SIZE(a)
Definition: main.h:24
Definition: fxglobalskm.h:353
PFX_DRIVER_GLOBALS fxDriverGlobals
#define EXP_IS_PTR_ALIGNED_ON_BOUNDARY(_pointer, _alignment)
Definition: fxbugcheck.h:38
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
VOID FxUnregisterBugCheckCallback(__inout PFX_DRIVER_GLOBALS FxDriverGlobals)
NTSTATUS AuxKlibGetBugCheckData(_Inout_ PKBUGCHECK_DATA BugCheckData)
Definition: aux_klib.c:178
PCHAR WdfLdrType
Definition: version.cpp:108
KBUGCHECK_REASON_CALLBACK_RECORD BugCheckCallbackRecord
Definition: fxglobals.h:796
_Must_inspect_result_ NTSTATUS FxpGetImageBase(__in PDRIVER_OBJECT DriverObject, __out PVOID *ImageBase, __out PULONG ImageSize)
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
KBUGCHECK_CALLBACK_REASON
Definition: ketypes.h:247
_Must_inspect_result_ NTSTATUS Register(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _FX_DRIVER_TRACKER_CACHE_AWARE::_FX_DRIVER_TRACKER_ENTRY * PFX_DRIVER_TRACKER_ENTRY
void exit(int exitcode)
Definition: _exit.c:33
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD _Inout_ PVOID ReasonSpecificData
Definition: ketypes.h:256
PFX_DRIVER_GLOBALS FxDriverGlobals
Definition: fxbugcheck.h:82
struct _FX_DRIVER_TRACKER_CACHE_AWARE::_FX_DRIVER_TRACKER_ENTRY FX_DRIVER_TRACKER_ENTRY
PVOID PVOID PWCHAR PVOID USHORT PULONG Reason
Definition: env.c:47
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
#define FX_MAX_DUMP_DRIVER_INFO_COUNT
Definition: fxbugcheck.h:73
ULONG BugCheckCode
Definition: aux_klib.h:46
WDF_MINOR_VERSION Minor
Definition: fxldr.h:123
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ALL_PROCESSOR_GROUPS
Definition: ntbasedef.h:644
#define EXP_ALIGN_UP_PTR_ON_BOUNDARY(_length, _alignment)
Definition: fxbugcheck.h:30
struct _KBUGCHECK_SECONDARY_DUMP_DATA * PKBUGCHECK_SECONDARY_DUMP_DATA
MxLockNoDynam FxDriverGlobalsListLock
Definition: fxglobals.h:772
Definition: ps.c:97