ReactOS  0.4.15-dev-1632-g4e289ce
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 {
128 // NTSTATUS status = STATUS_UNSUCCESSFUL;
129 // ULONG modulesSize = 0;
130 // AUX_MODULE_EXTENDED_INFO* modules = NULL;
131 // AUX_MODULE_EXTENDED_INFO* module;
132 // PVOID addressInImage = NULL;
133 // ULONG numberOfModules;
134 // ULONG i;
135 
136 // //
137 // // Basic validation.
138 // //
139 // if (NULL == DriverObject || NULL == ImageBase || NULL == ImageSize) {
140 // status = STATUS_INVALID_PARAMETER;
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 // //
153 // status = AuxKlibInitialize();
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 // //
174 // modules = (AUX_MODULE_EXTENDED_INFO*) ExAllocatePoolWithTag(PagedPool,
175 // modulesSize,
176 // '30LW');
177 // if (NULL == modules) {
178 // status = STATUS_INSUFFICIENT_RESOURCES;
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 
208 // status = STATUS_SUCCESS;
209 // goto exit;
210 // }
211 // module++;
212 // }
213 
214 // status = STATUS_NOT_FOUND;
215 
216 // exit:
217 
218 // if (modules != NULL) {
219 // ExFreePool(modules);
220 // modules = NULL;
221 // }
222 
223 // return status;
225  return STATUS_NOT_IMPLEMENTED;
226 }
227 
229 BOOLEAN
231  __inout PFX_DRIVER_GLOBALS FxDriverGlobals
232  )
233 /*++
234 
235 Routine Description:
236 
237  This routine evaluates whether the driver's IFR data has to be written to
238  the mini-dump file.
239 
240 Arguments:
241 
242  FxDriverGlobals - The driver globals of the wdf driver.
243 
244 Return Value:
245 
246  TRUE - Indicates this driver's IFR log is to be captured in dump.
247  FALSE - Indicates this driver's log is (probably) not of interest.
248 
249 --*/
250 {
251  // PVOID codeAddr = NULL;
252  // BOOLEAN found = FALSE;
253  // KBUGCHECK_DATA bugCheckData = {0};
254 
255  // if (FxDriverGlobals->FxForceLogsInMiniDump) {
256  // return TRUE;
257  // }
258 
259  // //
260  // // Retrieve the bugcheck parameters.
261  // //
262  // bugCheckData.BugCheckDataSize = sizeof(KBUGCHECK_DATA);
263  // AuxKlibGetBugCheckData(&bugCheckData);
264 
265  // //
266  // // Check whether the code address that caused the bugcheck is from this wdf
267  // // driver.
268  // //
269  // switch (bugCheckData.BugCheckCode) {
270 
271  // case KERNEL_APC_PENDING_DURING_EXIT: // 0x20
272  // codeAddr = (PVOID)bugCheckData.Parameter1;
273  // found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals);
274  // break;
275 
276  // case KMODE_EXCEPTION_NOT_HANDLED: // 0x1E
277  // case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED: // 0x7E
278  // case KERNEL_MODE_EXCEPTION_NOT_HANDLED: // 0x8E
279  // codeAddr = (PVOID)bugCheckData.Parameter2;
280  // found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals);
281  // break;
282 
283  // case PAGE_FAULT_IN_NONPAGED_AREA: // 0x50
284  // codeAddr = (PVOID)bugCheckData.Parameter3;
285  // found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals);
286  // break;
287 
288  // case IRQL_NOT_LESS_OR_EQUAL: // 0xA
289  // case DRIVER_IRQL_NOT_LESS_OR_EQUAL: // 0xD1
290  // codeAddr = (PVOID)bugCheckData.Parameter4;
291  // found = FxpIsAddressKnownToWdf(codeAddr, FxDriverGlobals);
292  // break;
293  // }
294 
295  // //
296  // // If the code address was found in the wdf driver, then set the flag in the
297  // // driver globals to indicate that the IFR data has to be written to the
298  // // mini-dump.
299  // //
300  // if (found) {
301  // FxDriverGlobals->FxForceLogsInMiniDump = TRUE;
302  // }
303  // return found;
305  return FALSE;
306 }
307 
308 VOID
309 STDCALL
314  __in ULONG ReasonSpecificLength
315  )
316 
317 /*++
318 
319 Routine Description:
320 
321  BugCheck callback routine for WDF
322 
323 Arguments:
324 
325  Reason - Must be KbCallbackSecondaryData
326  Record - Supplies the bugcheck record previously registered
327  ReasonSpecificData - Pointer to KBUGCHECK_SECONDARY_DUMP_DATA
328  ReasonSpecificLength - Sizeof(ReasonSpecificData)
329 
330 Return Value:
331 
332  None
333 
334 Notes:
335  When a bugcheck happens the kernel bugcheck processor will make two passes
336  of all registered BugCheckCallbackRecord routines. The first pass, called
337  the "sizing pass" essentially queries all the callbacks to collect the
338  total size of the secondary dump data. In the second pass the actual data
339  is captured to the dump.
340 
341 --*/
342 
343 {
346  ULONG logSize;
347  BOOLEAN writeLog = FALSE;
348 
350  UNREFERENCED_PARAMETER(ReasonSpecificLength);
351 
352  ASSERT(ReasonSpecificLength >= sizeof(KBUGCHECK_SECONDARY_DUMP_DATA));
353  ASSERT(Reason == KbCallbackSecondaryDumpData);
354 
356 
357  //
358  // See if the IFR's minimum amount of data can fit in the dump
359  //
360  if (dumpData->MaximumAllowed < FxIFRMinLogSize) {
361  return;
362  }
363 
364  //
365  // Get the driver globals containing the bugcheck callback record.
366  //
369  BugCheckCallbackRecord);
370 
371  //
372  // If there is not IFR data, then this bugcheck callback does not have any
373  // data to write to the minidump.
374  //
376  return;
377  }
378 
379  //
380  // Size is the length of the buffer which we log to. It should also include
381  // the size of the header (which was subtracted out in FxIFRStart).
382  //
383  logSize = ((PWDF_IFR_HEADER) fxDriverGlobals->WdfLogHeader)->Size +
384  sizeof(WDF_IFR_HEADER);
385 
386  ASSERT(FxIFRMinLogSize <= logSize && logSize <= FxIFRMaxLogSize);
387 
388  //
389  // Check whether log can fit in the dump.
390  //
391  if (logSize > dumpData->MaximumAllowed) {
392  return;
393  }
394 
395  //
396  // Check whether this log is the one to copy.
397  //
399  //
400  // Let everyone know that we got the best match.
401  //
403 
404  //
405  // Exact match driver.
406  //
407  writeLog = TRUE;
408  }
410  //
411  // So far we didn't get a perfect match. Make a best effort
412  // to find a good candidate for the driver dump log.
413  //
416  fxDriverGlobals) {
417  //
418  // Best effort match driver.
419  //
420  writeLog = TRUE;
421  }
422  }
423 
424  if (writeLog) {
426  dumpData->OutBufferLength = logSize;
427  dumpData->Guid = WdfDumpGuid;
428  }
429 }
430 
431 VOID
433  __inout PFX_DRIVER_GLOBALS FxDriverGlobals,
435  )
436 {
437  UNICODE_STRING funcName;
438  PKBUGCHECK_REASON_CALLBACK_RECORD callbackRecord;
440  BOOLEAN enableDriverTracking;
441 
442  //
443  // If any problem during this setup, disable driver tracking.
444  //
445  enableDriverTracking = FxDriverGlobals->FxTrackDriverForMiniDumpLog;
446  FxDriverGlobals->FxTrackDriverForMiniDumpLog = FALSE;
447 
448  //
449  // Zero out callback record.
450  //
451  callbackRecord = &FxDriverGlobals->BugCheckCallbackRecord;
452  RtlZeroMemory(callbackRecord, sizeof(KBUGCHECK_REASON_CALLBACK_RECORD));
453 
454  //
455  // Get the Image base address and size before registering the bugcheck
456  // callbacks. If the image base address and size cannot be computed,
457  // then the bugcheck callbacks depend on these values being properly
458  // set.
459  //
460  FxDriverGlobals->ImageAddress = NULL;
461  FxDriverGlobals->ImageSize = 0;
462 
464  &FxDriverGlobals->ImageAddress,
465  &FxDriverGlobals->ImageSize))) {
466  goto Done;
467  }
468 
469 
470 
471 
472 
473 
474 
475 
476 
477 
478  //
479  // The KeRegisterBugCheckReasonCallback exists for xp sp1 and above. So
480  // check whether this function is defined on the current OS and register
481  // for the bugcheck callback only if this function is defined.
482  //
483  RtlInitUnicodeString(&funcName, L"KeRegisterBugCheckReasonCallback");
485  MmGetSystemRoutineAddress(&funcName);
486 
487  if (NULL == funcPtr) {
488  goto Done;
489  }
490 
491  //
492  // Register this driver with driver tracker.
493  //
494  if (enableDriverTracking) {
496  FxDriverGlobals))) {
497  FxDriverGlobals->FxTrackDriverForMiniDumpLog = TRUE;
498  }
499  }
500 
501  //
502  // Initialize the callback record.
503  //
504  KeInitializeCallbackRecord(callbackRecord);
505 
506  //
507  // Register the bugcheck callback.
508  //
509  funcPtr(callbackRecord,
511  KbCallbackSecondaryDumpData,
512  (PUCHAR)FxDriverGlobals->Public.DriverName);
513 
514  ASSERT(callbackRecord->CallbackRoutine != NULL);
515 
516 Done:;
517 }
518 
519 VOID
521  __inout PFX_DRIVER_GLOBALS FxDriverGlobals
522  )
523 {
524  UNICODE_STRING funcName;
525  PKBUGCHECK_REASON_CALLBACK_RECORD callbackRecord;
527 
528  callbackRecord = &FxDriverGlobals->BugCheckCallbackRecord;
529  if (NULL == callbackRecord->CallbackRoutine) {
530  goto Done;
531  }
532 
533  //
534  // The KeDeregisterBugCheckReasonCallback exists for xp sp1 and above. So
535  // check whether this function is defined on the current OS and deregister
536  // from the bugcheck callback only if this function is defined.
537  //
538  RtlInitUnicodeString(&funcName, L"KeDeregisterBugCheckReasonCallback");
540  MmGetSystemRoutineAddress(&funcName);
541 
542  if (NULL == funcPtr) {
543  goto Done;
544  }
545 
546  funcPtr(callbackRecord);
547  callbackRecord->CallbackRoutine = NULL;
548 
549  //
550  // Deregister this driver with driver tracker.
551  //
552  if (FxDriverGlobals->FxTrackDriverForMiniDumpLog) {
553  FxLibraryGlobals.DriverTracker.Deregister(FxDriverGlobals);
554  }
555 
556 Done:;
557 }
558 
559 VOID
560 STDCALL
565  __in ULONG ReasonSpecificLength
566  )
567 
568 /*++
569 
570 Routine Description:
571 
572  Global (framework-library) BugCheck callback routine for WDF
573 
574 Arguments:
575 
576  Reason - Must be KbCallbackSecondaryData
577  Record - Supplies the bugcheck record previously registered
578  ReasonSpecificData - Pointer to KBUGCHECK_SECONDARY_DUMP_DATA
579  ReasonSpecificLength - Sizeof(ReasonSpecificData)
580 
581 Return Value:
582 
583  None
584 
585 Notes:
586  When a bugcheck happens the kernel bugcheck processor will make two passes
587  of all registered BugCheckCallbackRecord routines. The first pass, called
588  the "sizing pass" essentially queries all the callbacks to collect the
589  total size of the secondary dump data. In the second pass the actual data
590  is captured to the dump.
591 
592 --*/
593 
594 {
596  ULONG dumpSize;
597 
599  UNREFERENCED_PARAMETER(ReasonSpecificLength);
600 
601  ASSERT(ReasonSpecificLength >= sizeof(KBUGCHECK_SECONDARY_DUMP_DATA));
602  ASSERT(Reason == KbCallbackSecondaryDumpData);
603 
607  //
608  // See if the bugcheck driver info is more than can fit in the dump
609  //
610  if (dumpData->MaximumAllowed < dumpSize) {
611  dumpSize = EXP_ALIGN_DOWN_ON_BOUNDARY(
612  dumpData->MaximumAllowed,
613  sizeof(FX_DUMP_DRIVER_INFO_ENTRY));
614  }
615 
616  if (0 == dumpSize) {
617  goto Done;
618  }
619 
620  //
621  // Ok, provide the info about the bugcheck data.
622  //
624  dumpData->OutBufferLength = dumpSize;
625  dumpData->Guid = WdfDumpGuid2;
626 
627 Done:;
628 }
629 
630 VOID
632 {
634  UNICODE_STRING funcName;
635  PKBUGCHECK_REASON_CALLBACK_RECORD callbackRecord;
637  SIZE_T arraySize;
638  ULONG arrayCount;
639 
640 
641  callbackRecord = &FxLibraryGlobals.BugCheckCallbackRecord;
642  RtlZeroMemory(callbackRecord, sizeof(KBUGCHECK_REASON_CALLBACK_RECORD));
643 
647 
648 
649 
650 
651 
652 
653 
654 
655 
656 
657  //
658  // The KeRegisterBugCheckReasonCallback exists for xp sp1 and above. So
659  // check whether this function is defined on the current OS and register
660  // for the bugcheck callback only if this function is defined.
661  //
662  RtlInitUnicodeString(&funcName, L"KeRegisterBugCheckReasonCallback");
664  MmGetSystemRoutineAddress(&funcName);
665 
666  if (NULL == funcPtr) {
667  goto Done;
668  }
669 
671  arrayCount = FX_DUMP_DRIVER_INFO_INCREMENT;
672 
675  NonPagedPool,
676  arraySize,
677  FX_TAG);
678 
680  goto Done;
681  }
682 
684 
685  //
686  // Init first entry for the framework.
687  //
689  FxLibraryGlobals.BugCheckDriverInfo[0].Version.Major = __WDF_MAJOR_VERSION;
690  FxLibraryGlobals.BugCheckDriverInfo[0].Version.Minor = __WDF_MINOR_VERSION;
691  FxLibraryGlobals.BugCheckDriverInfo[0].Version.Build = __WDF_BUILD_NUMBER;
692 
696  WdfLdrType);
697 
698  if (!NT_SUCCESS(status)) {
699  ASSERT(FALSE);
701  }
702 
704 
705  //
706  // Initialize the callback record.
707  //
708  KeInitializeCallbackRecord(callbackRecord);
709 
710  //
711  // Register the bugcheck callback.
712  //
713  funcPtr(callbackRecord,
715  KbCallbackSecondaryDumpData,
716  (PUCHAR)WdfLdrType);
717 
718  ASSERT(callbackRecord->CallbackRoutine != NULL);
719 
720 Done:;
721 }
722 
723 VOID
725 {
726  UNICODE_STRING funcName;
727  PKBUGCHECK_REASON_CALLBACK_RECORD callbackRecord;
729 
730  //
731  // Deregister callback.
732  //
733 
734 
735 
736 
737 
738 
739 
740  callbackRecord = &FxLibraryGlobals.BugCheckCallbackRecord;
741  if (NULL == callbackRecord->CallbackRoutine) {
742  goto Done;
743  }
744 
745  //
746  // The KeDeregisterBugCheckReasonCallback exists for xp sp1 and above. So
747  // check whether this function is defined on the current OS and deregister
748  // from the bugcheck callback only if this function is defined.
749  //
750  RtlInitUnicodeString(&funcName, L"KeDeregisterBugCheckReasonCallback");
752  MmGetSystemRoutineAddress(&funcName);
753 
754  if (NULL == funcPtr) {
755  goto Done;
756  }
757 
758  funcPtr(callbackRecord);
759  callbackRecord->CallbackRoutine = NULL;
760 
761  //
762  // Release memory.
763  //
765  goto Done;
766  }
767 
768  //
769  // Dynamic KMDF framework is unloading, make sure there is only one entry
770  // left in the driver info array; the framework lib was using this entry
771  // to store its version.
772  //
774 
777 
780 
781 Done:;
782 }
783 
784 VOID
786  __in PFX_DRIVER_GLOBALS FxDriverGlobals
787  )
788 {
789  KIRQL irql;
790  PFX_DUMP_DRIVER_INFO_ENTRY driverInfo = NULL;
791  PFX_DUMP_DRIVER_INFO_ENTRY oldDriverInfo = NULL;
792  ULONG newCount = 0;
793 
794  //
795  // Clear driver index (0-based). Drivers do not use index 0.
796  //
797  FxDriverGlobals->BugCheckDriverInfoIndex = 0;
798 
800  return;
801  }
802 
804 
805  //
806  // Make sure we have enough space, else allocate some more memory.
807  //
810 
811  //
812  // Just exit if no more space in dump buffer.
813  //
816  ASSERT(FALSE);
817  goto Done;
818  }
819 
822 
823  //
824  // Allocate new buffer to hold driver info.
825  //
827  NonPagedPool,
828  sizeof(FX_DUMP_DRIVER_INFO_ENTRY)* newCount,
829  FX_TAG);
830 
831  if (NULL == driverInfo) {
832  goto Done;
833  }
834 
835  //
836  // Copy data from old to new buffer.
837  //
838  RtlCopyMemory(driverInfo,
841  sizeof(FX_DUMP_DRIVER_INFO_ENTRY));
842  //
843  // Ok, replace global pointer and its count.
844  //
845  oldDriverInfo = FxLibraryGlobals.BugCheckDriverInfo;
848  driverInfo = NULL; // just in case.
849 
850  //
851  // Free old memory.
852  //
853  MxMemory::MxFreePool(oldDriverInfo);
854  oldDriverInfo = NULL;
855  }
856 
859  //
860  // Compute ptr to free entry.
861  //
862  driverInfo = FxLibraryGlobals.BugCheckDriverInfo +
864  //
865  // Cache some of this driver's info.
866  //
867  driverInfo->FxDriverGlobals = FxDriverGlobals;
868  driverInfo->Version = FxDriverGlobals->WdfBindInfo->Version;
869 
870  C_ASSERT(sizeof(driverInfo->DriverName) ==
871  sizeof(FxDriverGlobals->Public.DriverName));
872  RtlCopyMemory(driverInfo->DriverName,
873  FxDriverGlobals->Public.DriverName,
874  sizeof(driverInfo->DriverName));
875  driverInfo->DriverName[ARRAY_SIZE(driverInfo->DriverName) - 1] = '\0';
876 
877  //
878  // Cache this index for later when the driver is removed.
879  //
880  FxDriverGlobals->BugCheckDriverInfoIndex =
882 
883  //
884  // Update global index.
885  //
887 
888 Done:
889 
891 }
892 
893 VOID
895  __in PFX_DRIVER_GLOBALS FxDriverGlobals
896  )
897 {
898  KIRQL irql;
899  PFX_DUMP_DRIVER_INFO_ENTRY driverInfo = NULL;
900  ULONG driverIndex = 0;
901  ULONG shiftCount = 0;
902  ULONG i = 0;
903 
905 
906  //
907  // Zero means 'not used'.
908  //
909  driverIndex = FxDriverGlobals->BugCheckDriverInfoIndex;
910  if (0 == driverIndex) {
911  goto Done;
912  }
913 
914  //
915  // Check if feature is not supported.
916  //
918  ASSERT(FALSE); // driverIndex > 0 with NULL array?
919  goto Done;
920  }
921 
922 
925 
926  //
927  // Index boundary validation.
928  //
929  if (driverIndex >= FxLibraryGlobals.BugCheckDriverInfoIndex) {
930  ASSERT(FALSE);
931  goto Done;
932  }
933 
934  //
935  // Compute ptr to driver info.
936  //
937  driverInfo = FxLibraryGlobals.BugCheckDriverInfo + driverIndex;
938 
939  //
940  // Double-check that this is the same driver.
941  //
942  if (driverInfo->FxDriverGlobals != FxDriverGlobals) {
943  ASSERT(FALSE);
944  goto Done;
945  }
946 
947  //
948  // Shift memory to fill hole and update global free index.
949  //
950  shiftCount = FxLibraryGlobals.BugCheckDriverInfoIndex - driverIndex - 1;
951  if (shiftCount > 0) {
952  RtlMoveMemory(driverInfo,
953  driverInfo + 1,
954  shiftCount * sizeof(FX_DUMP_DRIVER_INFO_ENTRY));
955  }
956 
958 
959  //
960  // Update cached index for all 'shifted' drivers.
961  //
962  for (i = driverIndex; i < FxLibraryGlobals.BugCheckDriverInfoIndex; ++i) {
964  BugCheckDriverInfoIndex--;
965  }
966 
967 Done:
968 
970 }
971 
972 //
973 // Driver usage tracker functions
974 //
975 NTSTATUS
977 {
978  //
979  // Global initialization. It balances the global Uninitialize function.
980  // The real init is actually done by the Register function the first time
981  // a driver registers with the device tracker.
982  //
984  m_PoolToFree = NULL;
985  m_EntrySize = 0;
986  m_Number = 0;
987 
988  return STATUS_SUCCESS;
989 }
990 
991 VOID
993 {
994  if (m_PoolToFree != NULL) {
995 
996 #ifdef DBG
997  for (ULONG index = 0; index < m_Number; ++index) {
998  PFX_DRIVER_TRACKER_ENTRY driverUsage = NULL;
999  driverUsage = GetProcessorDriverEntryRef(index);
1000  ASSERT(NULL == driverUsage->FxDriverGlobals);
1001  }
1002 #endif
1004  m_PoolToFree = NULL;
1005  }
1006 
1007  m_DriverUsage = NULL;
1008  m_Number = 0;
1009 }
1010 
1011 NTSTATUS
1013  __in PFX_DRIVER_GLOBALS /* FxDriverGlobals */
1014  )
1015 {
1017  ULONG paddedSize = 0;
1018  ULONG index = 0;
1020  PFX_DRIVER_TRACKER_ENTRY driverUsage = NULL;
1021  UNICODE_STRING funcName;
1022  PVOID funcPtr = NULL;
1023 
1024  //
1025  // Nothing to do if tracker is already initialized. No need for a lock
1026  // here since PnP already serializes driver initialization.
1027  //
1028  if (m_PoolToFree != NULL) {
1029  ASSERT(m_DriverUsage != NULL && m_Number != 0);
1031  goto Done;
1032  }
1033 
1034  //
1035  // Intialize the procgrp down level library.
1036  //
1037  // WdmlibProcgrpInitialize(); __REACTOS__ : haha we don't support ProcGrp
1038 
1039  //
1040  // Capture maximum number of processors.
1041  //
1042  RtlInitUnicodeString(&funcName, L"KeQueryMaximumProcessorCountEx");
1043  funcPtr = MmGetSystemRoutineAddress(&funcName);
1044  if (funcPtr != NULL) {
1045  //
1046  // Win 7 and forward.
1047  //
1050  }
1051  else {
1052  RtlInitUnicodeString(&funcName, L"KeQueryMaximumProcessorCount");
1053  funcPtr = MmGetSystemRoutineAddress(&funcName);
1054  if (funcPtr != NULL) {
1055  //
1056  // Windows Server 2008.
1057  //
1059  }
1060  else {
1065  //
1066  // XP (Major=5, Minor>0) and Vista (Major=6, Minor=0).
1067  //
1068  m_Number = (ULONG)(*((CCHAR *)&KeNumberProcessors));
1069  }
1070  else {
1071  //
1072  // This feature is not supported for Windows 2000.
1073  //
1074  ASSERT(FALSE);
1076  goto Done;
1077  }
1078  }
1079  }
1080 
1081  //
1082  // Validate upper bound.
1083  //
1086  goto Done;
1087  }
1088 
1089  //
1090  // Determine padded size of each tracking entry structure.
1091  //
1092  if (m_Number > 1 ) {
1093  RtlInitUnicodeString(&funcName, L"KeGetRecommendedSharedDataAlignment");
1094  funcPtr = MmGetSystemRoutineAddress(&funcName);
1095 
1096  if (funcPtr != NULL) {
1097  //
1098  //XP and forward
1099  //
1100  paddedSize = ((PFN_KE_GET_RECOMMENDED_SHARED_DATA_ALIGNMENT)funcPtr)();
1101  ASSERT ((paddedSize & (paddedSize - 1)) == 0);
1102  }
1103  else {
1104  //
1105  // This feature is not supported for Windows 2000.
1106  //
1108  goto Done;
1109  }
1110  }
1111  else {
1112  paddedSize = sizeof(FX_DRIVER_TRACKER_ENTRY);
1113  }
1114 
1115  ASSERT(sizeof(FX_DRIVER_TRACKER_ENTRY) <= paddedSize);
1116 
1117  //
1118  // Remember the size.
1119  //
1120  m_EntrySize = paddedSize;
1121 
1123  NonPagedPool,
1124  paddedSize * m_Number,
1125  FX_TAG);
1126  if (NULL == pool) {
1128  goto Done;
1129  }
1130 
1131  //
1132  // Check if pool is aligned if this is a multi-proc.
1133  //
1134  if ((m_Number > 1) && !EXP_IS_PTR_ALIGNED_ON_BOUNDARY(pool, paddedSize)) {
1135  //
1136  // We will allocate a padded size, free the old pool.
1137  //
1138  ExFreePool(pool);
1139 
1140  //
1141  // Allocate enough padding so we can start the refs on an aligned boundary
1142  //
1144  NonPagedPool,
1145  paddedSize * m_Number + paddedSize,
1146  FX_TAG);
1147  if (NULL == pool) {
1149  goto Done;
1150  }
1151 
1152  driverUsage = (PFX_DRIVER_TRACKER_ENTRY)
1153  EXP_ALIGN_UP_PTR_ON_BOUNDARY(pool, paddedSize);
1154 
1155  }
1156  else {
1157  //
1158  // Already aligned pool.
1159  //
1160  driverUsage = pool;
1161  }
1162 
1163  //
1164  // Remember the pool block to free.
1165  //
1166  m_PoolToFree = pool;
1167  m_DriverUsage = driverUsage;
1168 
1169  //
1170  // Init driver usage entries.
1171  //
1172  for (index = 0; index < m_Number; ++index) {
1173  driverUsage = GetProcessorDriverEntryRef(index);
1174  driverUsage->FxDriverGlobals = NULL;
1175  }
1176 
1177  //
1178  // All done.
1179  //
1181 
1182 Done:
1183  return status;
1184 }
1185 
1186 VOID
1188  __in PFX_DRIVER_GLOBALS FxDriverGlobals
1189  )
1190 {
1191  ULONG index = 0;
1192  PFX_DRIVER_TRACKER_ENTRY driverUsage = NULL;
1193 
1194  //
1195  // Cleanup any refs to this driver's globals.
1196  //
1197  if (m_PoolToFree != NULL) {
1198 
1199  ASSERT(m_DriverUsage != NULL && m_Number != 0);
1200 
1201  for (index = 0; index < m_Number; ++index) {
1202  driverUsage = GetProcessorDriverEntryRef(index);
1203  if (driverUsage->FxDriverGlobals == FxDriverGlobals) {
1204  driverUsage->FxDriverGlobals = NULL;
1205  }
1206  }
1207  }
1208 }
1209 
1210 } // extern "C"
ULONG(* PFN_KE_QUERY_MAXIMUM_PROCESSOR_COUNT_EX)(__in USHORT GroupNumber)
Definition: fxglobalskm.h:204
volatile PFX_DRIVER_GLOBALS FxDriverGlobals
Definition: fxglobalskm.h:354
BOOLEAN FxTrackDriverForMiniDumpLog
Definition: fxglobals.h:483
return STATUS_NOT_SUPPORTED
#define _Must_inspect_result_
Definition: no_sal2.h:62
PFX_DRIVER_TRACKER_ENTRY m_DriverUsage
Definition: fxglobalskm.h:442
_Must_inspect_result_ BOOLEAN FxpBugCheckCallbackFilter(__inout PFX_DRIVER_GLOBALS FxDriverGlobals)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
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
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
unsigned char * PUCHAR
Definition: retypes.h:3
BOOLEAN(* 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
LONG NTSTATUS
Definition: precomp.h:26
#define KeInitializeCallbackRecord(CallbackRecord)
Definition: kefuncs.h:1399
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
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
return STATUS_NOT_IMPLEMENTED
WDF_BUILD_NUMBER Build
Definition: fxldr.h:124
#define FALSE
Definition: types.h:117
PVOID NTAPI MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
Definition: sysldr.c:3432
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)
#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:71
GLuint index
Definition: glext.h:6031
ULONG(* PFN_KE_GET_RECOMMENDED_SHARED_DATA_ALIGNMENT)(VOID)
Definition: fxglobalskm.h:222
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)
struct _WDF_IFR_HEADER * PWDF_IFR_HEADER
#define ROSWDFNOTIMPLEMENTED
Definition: fxglobals.h:52
#define STDCALL
Definition: wdf.h:45
#define ASSERT(a)
Definition: mode.c:45
#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
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#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
FxLibraryGlobalsType FxLibraryGlobals
Definition: globals.cpp:95
WDF_VERSION Version
Definition: fxbugcheck.h:83
BOOLEAN(* PFN_KE_DEREGISTER_BUGCHECK_REASON_CALLBACK)(__in PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecords)
Definition: fxglobalskm.h:92
#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)
CCHAR KeNumberProcessors
Definition: krnlinit.c:35
ULONG BugCheckDriverInfoIndex
Definition: fxglobals.h:780
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)
PCHAR WdfLdrType
Definition: version.cpp:108
KBUGCHECK_REASON_CALLBACK_RECORD BugCheckCallbackRecord
Definition: fxglobals.h:796
ULONG(* PFN_KE_QUERY_MAXIMUM_PROCESSOR_COUNT)(VOID)
Definition: fxglobalskm.h:210
_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
_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:45
#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
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