Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

ioassert.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1998 Microsoft Corporation 00004 00005 Module Name: 00006 00007 ioassert.c 00008 00009 Abstract: 00010 00011 This module implements basic support for driver correctness checks (which 00012 may be raised to debugger prompts, bugchecks, etc). 00013 00014 Author: 00015 00016 Adrian J. Oney (adriao) 20-Apr-1998 00017 00018 Environment: 00019 00020 Kernel mode 00021 00022 Revision History: 00023 00024 Known BUGBUGs: 00025 00026 --*/ 00027 00028 #include "iop.h" 00029 00030 #if (( defined(_X86_) ) && ( FPO )) 00031 #pragma optimize( "y", off ) // disable FPO for consistent stack traces 00032 #endif 00033 00034 #ifndef NO_SPECIAL_IRP 00035 00036 #ifdef ALLOC_PRAGMA 00037 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessTakeLock) 00038 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessReleaseLock) 00039 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessCheckUnderLock) 00040 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessProcessParams) 00041 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessProcessMessageText) 00042 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessApplyControl) 00043 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessThrowBugCheck) 00044 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessPrintBuffer) 00045 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessPrintParamData) 00046 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessPrompt) 00047 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessAddressToFileHeader) 00048 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessPrintIrp) 00049 #pragma alloc_text(PAGEVRFY, IopDriverCorrectnessPrintIrpStack) 00050 #endif // ALLOC_PRAGMA 00051 00052 PULONG IopDcControlCurrent = NULL; 00053 LONG IopDcCurrentFrameSkips = -1; 00054 KIRQL IopDcControlIrql; 00055 KSPIN_LOCK IopDcControlLock; 00056 ULONG IopDcControlInitial = (ULONG) -1; 00057 ULONG IopDcControlOverride = (ULONG) -1; 00058 00059 #ifdef ALLOC_DATA_PRAGMA 00060 #pragma data_seg("PAGEVRFY$data") 00061 #endif 00062 00063 // 00064 // When invoking the driver check macro's, pass Irps first, Routines second, 00065 // DevObj's third, and any Status's last... 00066 // 00067 DCPARAM_TYPE_ENTRY DcParamTable[] = { 00068 { DCPARAM_IRP, "Irp" }, 00069 { DCPARAM_ROUTINE, "Routine" }, 00070 { DCPARAM_DEVOBJ, "DevObj" }, 00071 { DCPARAM_STATUS, "Status" } 00072 }; 00073 00074 typedef struct _DCERROR_MESSAGE { 00075 00076 DCERROR_ID MessageID; 00077 PCDCERROR_CLASS MessageClass; 00078 PSTR MessageText; 00079 00080 } DCERROR_MESSAGE, *PDCERROR_MESSAGE; 00081 00082 // 00083 // These are the general "classifications" of errors, along with the default 00084 // flags that will be applied the first time this is hit. 00085 // 00086 // IopDcWdmDriverErrorFatal - 00087 // Anything in this class will cause the IO verifier to bugcheck if no 00088 // debugger is present. 00089 // 00090 // IopDcWdmDriverErrorNonFatal - 00091 // Anything in this class will not cause the IO verifier to bugcheck, but 00092 // will stop under the debugger. 00093 // 00094 // IopDcWdmDriverWarning - 00095 // Anything in this class will beep but continue without breaking in. 00096 // 00097 // IopDcWdmDriverPostponed - 00098 // Anything in this class will merely print and continue. 00099 // 00100 // IopDcWdmCoreError - 00101 // Issue in a core component (kernel or hal) 00102 // 00103 DCERROR_CLASS IopDcWdmDriverErrorFatal = 00104 { DIAG_BEEP | DIAG_FATAL_ERROR | DIAG_WDM_ERROR, "WDM DRIVER ERROR" }; 00105 00106 DCERROR_CLASS IopDcWdmDriverErrorNonFatal = 00107 { DIAG_BEEP | DIAG_WDM_ERROR, "WDM DRIVER ERROR" }; 00108 00109 DCERROR_CLASS IopDcWdmDriverWarning = 00110 { DIAG_BEEP | DIAG_ZAPPED, "WDM DRIVER WARNING" }; 00111 00112 DCERROR_CLASS IopDcWdmDriverPostponed = { DIAG_ZAPPED, "POSTPONED WDM DRIVER BUG" }; 00113 00114 DCERROR_CLASS IopDcWdmCoreError = { DIAG_BEEP, "CORE DRIVER ERROR" }; 00115 00116 // 00117 // This is the table of error messages. Note that we've numbered the error 00118 // message numbers continuously, so that they can be used as an indice into the 00119 // table. Also note these constants are published, so if asserts are removed 00120 // in the future, the current algorithm may need to be replaced by something 00121 // akin to a binary search (or perhaps padding will need to be added). 00122 // 00123 DCERROR_MESSAGE IopDcMessageTable[DCERROR_MAXIMUM - DCERROR_UNSPECIFIED] = { 00124 { DCERROR_UNSPECIFIED, NULL, NULL }, 00125 { DCERROR_DELETE_WHILE_ATTACHED, &IopDcWdmDriverErrorFatal, 00126 "A device is deleting itself while there is another device beneath it in " 00127 "the driver stack. This may be because the caller has forgotten to call " 00128 "IoDetachDevice first, or the lower driver may have incorrectly deleted " 00129 "itself." }, 00130 { DCERROR_DETACH_NOT_ATTACHED, &IopDcWdmDriverErrorFatal, 00131 "Driver has attempted to detach from device object %DevObj, which is not " 00132 "attached to anything. This may occur if detach was called twice on the " 00133 "same device object." }, 00134 { DCERROR_CANCELROUTINE_FORWARDED, &IopDcWdmDriverErrorFatal, 00135 "A driver has called IoCallDriver without setting the CancelRoutine in " 00136 "the Irp to NULL (Irp = %Irp )." }, 00137 { DCERROR_NULL_DEVOBJ_FORWARDED, &IopDcWdmDriverErrorFatal, 00138 "Caller has passed in NULL as a DeviceObject. This is fatal (Irp = %Irp )." 00139 }, 00140 { DCERROR_QUEUED_IRP_FORWARDED, &IopDcWdmDriverErrorFatal, 00141 "Caller is forwarding an IRP that is currently queued beneath it! The " 00142 "code handling IRPs returning STATUS_PENDING in this driver appears to " 00143 "be broken (Irp = %Irp )." }, 00144 { DCERROR_NEXTIRPSP_DIRTY, &IopDcWdmDriverErrorFatal, 00145 "Caller has incorrectly forwarded an IRP (control field not zerod). The " 00146 "driver should use IoCopyCurrentIrpStackLocationToNext or " 00147 "IoSkipCurrentIrpStackLocation. (Irp = %Irp )" }, 00148 { DCERROR_IRPSP_COPIED, &IopDcWdmDriverErrorFatal, 00149 "Caller has manually copied the stack and has inadvertantly copied the " 00150 "upper layer's completion routine. Please use " 00151 "IoCopyCurrentIrpStackLocationToNext. (Irp = %Irp )." }, 00152 { DCERROR_INSUFFICIENT_STACK_LOCATIONS, &IopDcWdmDriverErrorFatal, 00153 "This IRP is about to run out of stack locations. Someone may have " 00154 "forwarded this IRP from another stack (Irp = %Irp )." }, 00155 { DCERROR_QUEUED_IRP_COMPLETED, &IopDcWdmDriverErrorFatal, 00156 "Caller is completing an IRP that is currently queued beneath it! The " 00157 "code handling IRPs returning STATUS_PENDING in this driver appears to be " 00158 "broken. (Irp = %Irp )" }, 00159 { DCERROR_FREE_OF_INUSE_TRACKED_IRP, &IopDcWdmDriverErrorFatal, 00160 "Caller of IoFreeIrp is freeing an IRP that is still in use! (Original " 00161 "Irp = %Irp1, Irp in usage is %Irp2 )" }, 00162 { DCERROR_FREE_OF_INUSE_IRP, &IopDcWdmDriverErrorFatal, 00163 "Caller of IoFreeIrp is freeing an IRP that is still in use! (Irp = %Irp )" 00164 }, 00165 { DCERROR_FREE_OF_THREADED_IRP, &IopDcWdmDriverErrorFatal, 00166 "Caller of IoFreeIrp is freeing an IRP that is still enqueued against a " 00167 "thread! (Irp = %Irp )" }, 00168 { DCERROR_REINIT_OF_ALLOCATED_IRP_WITH_QUOTA, &IopDcWdmDriverErrorFatal, 00169 "Caller of IoInitializeIrp has passed an IRP that was allocated with " 00170 "IoAllocateIrp. This is illegal and unneccessary, and has caused a quota " 00171 "leak. Check the documentation for IoReuseIrp if this IRP is being " 00172 "recycled." }, 00173 { DCERROR_PNP_IRP_BAD_INITIAL_STATUS, &IopDcWdmDriverErrorNonFatal, 00174 "Any PNP IRP must have status initialized to STATUS_NOT_SUPPORTED " 00175 "(Irp = %Irp )." }, 00176 { DCERROR_POWER_IRP_BAD_INITIAL_STATUS, &IopDcWdmDriverErrorNonFatal, 00177 "Any Power IRP must have status initialized to STATUS_NOT_SUPPORTED " 00178 "(Irp = %Irp )." }, 00179 { DCERROR_WMI_IRP_BAD_INITIAL_STATUS, &IopDcWdmDriverErrorNonFatal, 00180 "Any WMI IRP must have status initialized to STATUS_NOT_SUPPORTED " 00181 "(Irp = %Irp )." }, 00182 { DCERROR_SKIPPED_DEVICE_OBJECT, &IopDcWdmDriverErrorNonFatal, 00183 "Caller has forwarded an Irp while skipping a device object in the stack. " 00184 "The caller is probably sending IRPs to the PDO instead of to the device " 00185 "returned by IoAttachDeviceToDeviceStack (Irp = %Irp )." }, 00186 { DCERROR_BOGUS_FUNC_TRASHED, &IopDcWdmDriverErrorNonFatal, 00187 "Caller has trashed or has not properly copied IRP's stack (Irp = %Irp )." 00188 }, 00189 { DCERROR_BOGUS_STATUS_TRASHED, &IopDcWdmDriverErrorNonFatal, 00190 "Caller has changed the status field of an IRP it does not understand " 00191 "(Irp = %Irp )." }, 00192 { DCERROR_BOGUS_INFO_TRASHED, &IopDcWdmDriverErrorNonFatal, 00193 "Caller has changed the information field of an IRP it does not " 00194 "understand (Irp = %Irp )." }, 00195 { DCERROR_PNP_FAILURE_FORWARDED, &IopDcWdmDriverErrorNonFatal, // Grrr 00196 "Non-successful non-STATUS_NOT_SUPPORTED IRP status for IRP_MJ_PNP is " 00197 "being passed down stack (Irp = %Irp ). Failed PNP IRPs must be completed." 00198 }, 00199 { DCERROR_PNP_IRP_STATUS_RESET, &IopDcWdmDriverErrorNonFatal, 00200 "Previously set IRP_MJ_PNP status has been converted to " 00201 "STATUS_NOT_SUPPORTED. (Irp = %Irp )." }, 00202 { DCERROR_PNP_IRP_NEEDS_FDO_HANDLING, &IopDcWdmDriverErrorNonFatal, 00203 "FDO caller has not handled a required IRP. The FDO must either fail the " 00204 "IRP or set the IRP's status if it is not going change the IRP's status " 00205 "using a completion routine. (Irp = %Irp )." }, 00206 { DCERROR_PNP_IRP_FDO_HANDS_OFF, &IopDcWdmDriverErrorNonFatal, 00207 "FDO caller has responded to an IRP that is reserved for PDO use only. " 00208 "Stop it. (Irp = %Irp )" }, 00209 { DCERROR_POWER_FAILURE_FORWARDED, &IopDcWdmDriverErrorNonFatal, // Grrr 00210 "Non-successful non-STATUS_NOT_SUPPORTED IRP status for IRP_MJ_POWER is " 00211 "being passed down stack (Irp = %Irp ). Failed POWER IRPs must be " 00212 "completed." }, 00213 { DCERROR_POWER_IRP_STATUS_RESET, &IopDcWdmDriverErrorNonFatal, 00214 "Previously set IRP_MJ_POWER status has been converted to " 00215 "STATUS_NOT_SUPPORTED. (Irp = %Irp )." }, 00216 { DCERROR_INVALID_STATUS, &IopDcWdmDriverErrorNonFatal, 00217 "Driver has returned a suspicious status. This is probably due to an " 00218 "uninitiaized variable bug in the driver. (Irp = %Irp )" }, 00219 { DCERROR_UNNECCESSARY_COPY, &IopDcWdmDriverWarning, 00220 "Caller has copied the Irp stack but not set a completion routine. " 00221 "This is inefficient, use IoSkipCurrentIrpStackLocation instead " 00222 "(Irp = %Irp )." }, 00223 { DCERROR_SHOULDVE_DETACHED, &IopDcWdmDriverErrorFatal, 00224 "An IRP dispatch handler has not properly detached from the stack below " 00225 "it upon receiving a remove IRP. DeviceObject = %DevObj - Dispatch = " 00226 "%Routine - Irp = %Irp" }, 00227 { DCERROR_SHOULDVE_DELETED, &IopDcWdmDriverErrorFatal, 00228 "An IRP dispatch handler has not properly deleted it's device object upon " 00229 "receiving a remove IRP. DeviceObject = %DevObj - Dispatch = %Routine - " 00230 "Irp = %Irp" }, 00231 { DCERROR_MISSING_DISPATCH_FUNCTION, &IopDcWdmDriverErrorNonFatal, 00232 "This driver has not filled out a dispatch routine for a required IRP " 00233 "major function (Irp = %Irp )." }, 00234 { DCERROR_WMI_IRP_NOT_FORWARDED, &IopDcWdmDriverErrorNonFatal, 00235 "IRP_MJ_SYSTEM_CONTROL has been completed by someone other than the " 00236 "ProviderId. This IRP should either have been completed earlier or " 00237 "should have been passed down (Irp = %Irp ). The IRP was targetted at " 00238 "DeviceObject %DevObj" }, 00239 { DCERROR_DELETED_PRESENT_PDO, &IopDcWdmDriverErrorFatal, 00240 "An IRP dispatch handler for a PDO has deleted it's device object, but " 00241 "the hardware has not been reported as missing in a bus relations query. " 00242 "DeviceObject = %DevObj - Dispatch = %Routine - Irp = %Irp " }, 00243 { DCERROR_BUS_FILTER_ERRONEOUSLY_DETACHED, &IopDcWdmDriverErrorFatal, 00244 "A Bus Filter's IRP dispatch handler has detached upon receiving a remove " 00245 "IRP when the PDO is still alive. Bus Filters must clean up in " 00246 "FastIoDetach callbacks. DeviceObject = %DevObj - Dispatch = %Routine - " 00247 "Irp = %Irp" }, 00248 { DCERROR_BUS_FILTER_ERRONEOUSLY_DELETED, &IopDcWdmDriverErrorFatal, 00249 "An IRP dispatch handler for a bus filter has deleted it's device object, " 00250 "but the PDO is still present! Bus filters must clean up in FastIoDetach " 00251 "callbacks. DeviceObject = %DevObj - Dispatch = %Routine - Irp = %Irp" }, 00252 { DCERROR_INCONSISTANT_STATUS, &IopDcWdmDriverErrorFatal, 00253 "An IRP dispatch handler ( %Routine ) has returned a status that is " 00254 "inconsistent with the Irp's IoStatus.Status field. ( Irp = %Irp - " 00255 "Irp->IoStatus.Status = %Status1 - returned = %Status2 )" }, 00256 { DCERROR_UNINITIALIZED_STATUS, &IopDcWdmDriverErrorNonFatal, 00257 "An IRP dispatch handler has returned a status that is illegal " 00258 "(0xFFFFFFFF). This is probably due to an uninitialized stack variable. " 00259 "Please do an ln on address %lx and file a bug. (Irp = %Irp )" }, 00260 { DCERROR_IRP_RETURNED_WITHOUT_COMPLETION, &IopDcWdmDriverErrorFatal, 00261 "An IRP dispatch handler has returned without passing down or completing " 00262 "this Irp or someone forgot to return STATUS_PENDING. (Irp = %Irp )." }, 00263 { DCERROR_COMPLETION_ROUTINE_PAGABLE, &IopDcWdmDriverErrorFatal, 00264 "IRP completion routines must be in nonpagable code, and this one is not: " 00265 "%Routine. (Irp = %Irp )" }, 00266 { DCERROR_PENDING_BIT_NOT_MIGRATED, &IopDcWdmDriverErrorNonFatal, 00267 "A driver's completion routine ( %Routine ) has not marked the IRP " 00268 "pending if the PendingReturned field was set in the IRP passed to it. " 00269 "This may cause the OS to hang, especially if an error is returned by the " 00270 " stack. (Irp = %Irp )" }, 00271 { DCERROR_CANCELROUTINE_ON_FORWARDED_IRP, &IopDcWdmDriverErrorFatal, 00272 "A cancel routine has been set for an IRP that is currently being " 00273 "processed by drivers lower in the stack, possibly stomping their cancel " 00274 "routine (Irp = %Irp, Routine=%Routine )." }, 00275 { DCERROR_PNP_IRP_NEEDS_PDO_HANDLING, &IopDcWdmDriverErrorNonFatal, 00276 "PDO has not responded to a required IRP (Irp = %Irp )" }, 00277 { DCERROR_TARGET_RELATION_LIST_EMPTY, &IopDcWdmDriverErrorNonFatal, 00278 "PDO has forgotten to fill out the device relation list with the PDO for " 00279 "the TargetDeviceRelation query (Irp = %Irp )" }, 00280 { DCERROR_TARGET_RELATION_NEEDS_REF, &IopDcWdmDriverErrorFatal, 00281 "The code implementing the TargetDeviceRelation query has not called " 00282 "ObReferenceObject on the PDO (Irp = %Irp )." }, 00283 { DCERROR_BOGUS_PNP_IRP_COMPLETED, &IopDcWdmDriverErrorNonFatal, 00284 "Caller has completed a IRP_MJ_PNP it didn't understand instead of " 00285 "passing it down (Irp = %Irp )." }, 00286 { DCERROR_SUCCESSFUL_PNP_IRP_NOT_FORWARDED, &IopDcWdmDriverErrorNonFatal, 00287 "Caller has completed successful IRP_MJ_PNP instead of passing it down " 00288 "(Irp = %Irp )." }, 00289 { DCERROR_UNTOUCHED_PNP_IRP_NOT_FORWARDED, &IopDcWdmDriverErrorNonFatal, 00290 "Caller has completed untouched IRP_MJ_PNP (instead of passing the irp " 00291 "down) or non-PDO has failed the irp using illegal value of " 00292 "STATUS_NOT_SUPPORTED. (Irp = %Irp )." }, 00293 { DCERROR_BOGUS_POWER_IRP_COMPLETED, &IopDcWdmDriverErrorNonFatal, 00294 "Caller has completed a IRP_MJ_POWER it didn't understand instead of " 00295 "passing it down (Irp = %Irp )." }, 00296 { DCERROR_SUCCESSFUL_POWER_IRP_NOT_FORWARDED, &IopDcWdmDriverErrorFatal, 00297 "Caller has completed successful IRP_MJ_POWER instead of passing it down " 00298 "(Irp = %Irp )." }, 00299 { DCERROR_UNTOUCHED_POWER_IRP_NOT_FORWARDED, &IopDcWdmDriverErrorNonFatal, 00300 "Caller has completed untouched IRP_MJ_POWER (instead of passing the irp " 00301 "down) or non-PDO has failed the irp using illegal value of " 00302 "STATUS_NOT_SUPPORTED. (Irp = %Irp )." }, 00303 { DCERROR_PNP_QUERY_CAP_BAD_VERSION, &IopDcWdmDriverErrorFatal, 00304 "The version field of the query capabilities structure in a query " 00305 "capabilities IRP was not properly initialized. (Irp = %Irp )." }, 00306 { DCERROR_PNP_QUERY_CAP_BAD_SIZE, &IopDcWdmDriverErrorFatal, 00307 "The size field of the query capabilities structure in a query " 00308 "capabilities IRP was not properly initialized. (Irp = %Irp )." }, 00309 { DCERROR_PNP_QUERY_CAP_BAD_ADDRESS, &IopDcWdmDriverErrorNonFatal, 00310 "The address field of the query capabilities structure in a query " 00311 "capabilities IRP was not properly initialized to -1. (Irp = %Irp )." }, 00312 { DCERROR_PNP_QUERY_CAP_BAD_UI_NUM, &IopDcWdmDriverErrorNonFatal, 00313 "The UI Number field of the query capabilities structure in a query " 00314 "capabilities IRP was not properly initialized to -1. (Irp = %Irp )." }, 00315 { DCERROR_RESTRICTED_IRP, &IopDcWdmDriverErrorFatal, 00316 "A driver has sent an IRP that is restricted for system use only. " 00317 "(Irp = %Irp )." }, 00318 { DCERROR_REINIT_OF_ALLOCATED_IRP_WITHOUT_QUOTA, &IopDcWdmDriverWarning, 00319 "Caller of IoInitializeIrp has passed an IRP that was allocated with " 00320 "IoAllocateIrp. This is illegal, unneccessary, and negatively impacts " 00321 "performace in normal use. Check the documentation for IoReuseIrp if " 00322 "this IRP is being recycled." }, 00323 { DCERROR_UNFORWARDED_IRP_COMPLETED, &IopDcWdmDriverWarning, 00324 "The caller of IoCompleteRequest is completing an IRP that has never " 00325 "been forwarded via a call to IoCallDriver or PoCallDriver. This may " 00326 "be a bug. (Irp = %Irp )." }, 00327 { DCERROR_DISPATCH_CALLED_AT_BAD_IRQL, &IopDcWdmDriverErrorFatal, 00328 "A driver has forwarded an IRP at an IRQL that is illegal for this major" 00329 " code. " 00330 "(Irp = %Irp )." }, 00331 { DCERROR_BOGUS_MINOR_STATUS_TRASHED, &IopDcWdmDriverErrorFatal, 00332 "Caller has changed the status field of an IRP it does not understand " 00333 "(Irp = %Irp )." } 00334 }; 00335 00336 typedef struct _DC_OVERRIDE_TABLE { 00337 00338 DCERROR_ID MessageID; 00339 PSTR DriverName; 00340 PDCERROR_CLASS ReplacementClass; 00341 00342 } DC_OVERRIDE_TABLE, *PDC_OVERRIDE_TABLE; 00343 00344 // 00345 // This table contains things we've postponed. 00346 // 00347 DC_OVERRIDE_TABLE IopDcOverrideTable[] = { 00348 00349 // 00350 // These exist because verifier.exe cannot specify kernels or hals. We still 00351 // want a mechanism to allow complaints. 00352 // 00353 { DCERROR_UNSPECIFIED, "HAL.DLL", &IopDcWdmCoreError }, 00354 { DCERROR_UNSPECIFIED, "NTOSKRNL.EXE", &IopDcWdmCoreError }, 00355 { DCERROR_UNSPECIFIED, "NTKRNLMP.EXE", &IopDcWdmCoreError }, 00356 { DCERROR_UNSPECIFIED, "NTKRNLPA.EXE", &IopDcWdmCoreError }, 00357 { DCERROR_UNSPECIFIED, "NTKRPAMP.EXE", &IopDcWdmCoreError }, 00358 00359 // 00360 // ADRIAO BUGBUG 08/10/1999 - 00361 // NDIS doesn't call the shutdown handlers at power-off because many are 00362 // unstable and that adds seconds to shutdown. This is an unsafe design as 00363 // the miniport, which owns an IRQ, may find it's ports drop out from under 00364 // it when the *parent* powers off. 00365 // 00366 { DCERROR_SUCCESSFUL_POWER_IRP_NOT_FORWARDED, "NDIS.SYS", 00367 &IopDcWdmDriverPostponed }, 00368 00369 // 00370 // ADRIAO BUGBUG 08/10/1999 - 00371 // ACPI and PCI have to work together to handle wait-wake. In the 00372 // current design, ACPI.SYS gets an interface and does all the work itself. 00373 // The proper design should move the queueing to PCI, or tell PCI to leave 00374 // wait-wake IRPs alone for the given device. Cutting off any other bus 00375 // filters is a bad design. 00376 // 00377 { DCERROR_SUCCESSFUL_POWER_IRP_NOT_FORWARDED, "ACPI.SYS", 00378 &IopDcWdmDriverPostponed }, 00379 00380 // 00381 // ADRIAO BUGBUG 08/20/1999 - 00382 // This is on QueryCapabilities, which PCMCIA caches but should not. 00383 // NeilSa has postponed this one till NT 5.1 00384 // 00385 { DCERROR_SUCCESSFUL_PNP_IRP_NOT_FORWARDED, "PCMCIA.SYS", 00386 &IopDcWdmDriverPostponed }, 00387 00388 // 00389 // ADRIAO BUGBUG 08/20/1999 - 00390 // PCMCIA completes Queries for S-IRPs. NeilSa has postponed this one 00391 // till NT 5.1 00392 // 00393 { DCERROR_SUCCESSFUL_POWER_IRP_NOT_FORWARDED, "PCMCIA.SYS", 00394 &IopDcWdmDriverPostponed }, 00395 00396 // 00397 // ADRIAO BUGBUG 08/21/1999 - 00398 // SCSIPORT doesn't forward S0 Irps if the system is already in S0. 00399 // Consider if a PDO succeeds a Query-S1 IRP and then waits for either a 00400 // Set to S1, a new Query, or a Set to S0 meaning no transition will take 00401 // place after all. A filter between SCSIPORT and the PDO could fail the 00402 // Query-S1 on the way up. SCSIPORT knows the system has decided to stay in 00403 // S0, but it cuts such knowledge off from the PDO. Luckily today's list of 00404 // likely PDO's don't have such logic though. PeterWie has postponed this 00405 // one till NT 5.1 00406 // 00407 { DCERROR_SUCCESSFUL_POWER_IRP_NOT_FORWARDED, "SCSIPORT.SYS", 00408 &IopDcWdmDriverPostponed } 00409 }; 00410 00411 #ifdef ALLOC_DATA_PRAGMA 00412 #pragma data_seg() 00413 #endif 00414 00415 PCHAR 00416 KeBugCheckUnicodeToAnsi( 00417 IN PUNICODE_STRING UnicodeString, 00418 OUT PCHAR AnsiBuffer, 00419 IN ULONG MaxAnsiLength 00420 ); 00421 00422 VOID 00423 IopDriverCorrectnessTakeLock( 00424 IN PULONG ControlNew, 00425 IN LONG StackFramesToSkip 00426 ) 00427 /*++ 00428 00429 Description: 00430 00431 Worker routine for KD_ASSERT_OUT, takes the assertion spinlock. We do 00432 this because we *must* use a macro to instantiate a caller-specific 00433 tag and we cannot pass in that value along with a variable printf style 00434 debug output. Hence we must "pre-program" the output routine with the 00435 breakpoint ID, and use a spinlock to protect ourselves 00436 --*/ 00437 { 00438 ASSERT(IovpInitCalled); 00439 ExAcquireSpinLock( &IopDcControlLock, &IopDcControlIrql ); 00440 ASSERT(IopDcControlCurrent == NULL) ; 00441 IopDcControlCurrent = ControlNew ; 00442 IopDcCurrentFrameSkips = StackFramesToSkip ; 00443 } 00444 00445 VOID 00446 IopDriverCorrectnessReleaseLock( 00447 VOID 00448 ) 00449 /*++ 00450 00451 Description: 00452 00453 Worker routine for KD_ASSERT_OUT, see IopDiagSetAssertLock 00454 00455 --*/ 00456 { 00457 IopDcControlCurrent = NULL ; 00458 IopDcCurrentFrameSkips = -1 ; 00459 ExReleaseSpinLock( &IopDcControlLock, IopDcControlIrql ); 00460 } 00461 00462 NTSTATUS 00463 IopDriverCorrectnessCheckUnderLock( 00464 IN DCERROR_ID MessageID, 00465 IN ULONG MessageParameterMask, 00466 ... 00467 ) 00468 /*++ 00469 00470 Description: 00471 00472 This routine displays an assert and provides options for 00473 removing the breakpoint, changing to just a text-out, etc. 00474 00475 This routine is used as part of a macro for providing "Zappable" traps - 00476 IE, users get the option of changing how a specific instance of 00477 WDM_DEBUG_OUT in the code is handled (default is spew and break, options 00478 are spew or blow away for this boot). 00479 00480 Macro must call IopDiagSetAssertLock, IopDiagAssertPrintfUnderLock, and 00481 IopDiagReleaseAssertLock in order 00482 00483 DCPARAM_IRP*(count)+DCPARAM_ROUTINE*(count)+DCPARAM_DEVOBJ*(count), 00484 irp1, 00485 irp2, 00486 irp3, 00487 routine1, 00488 .., 00489 .., 00490 devobj1, 00491 00492 count can be a max of 3. 00493 00494 00495 Arguments: 00496 00497 Control - if present, this variable determines whether we will 00498 actually do anything. 00499 00500 if DIAG_ZAPPED is set we will print the assert text and return. 00501 if DIAG_CLEARED is set, we will neither print or stop. 00502 if DIAG_BEEP is set, we will beep if not zapped. 00503 00504 StackFramesToSkip - If this parameter is -1, it is not used. 00505 Otherwise, the assertion code will attempt to walk 00506 back the appropriate number of frames and 00507 determine the caller to blame based on return 00508 address. 00509 00510 IrpToFlag - IRP to print out failure data for if mishandling of 00511 this IRP was the source of the error. 00512 00513 AddressToFlag - Address that the assert should be blaimed on. This 00514 should be null if StackFramesToSkip is not -1. 00515 00516 AssertionClass - Text describing the overall class of the assert 00517 00518 AssertionText - Text specifically describing the assert. Carriage 00519 returns should not be embedded in the text, this 00520 routine will automatically ensure words are not split 00521 across the screen. 00522 00523 Notes: 00524 00525 The text will automagically be formatted and printed as such: 00526 00527 ASSERTION CLASS: ASSERTION TEXT ASSERTION TEXT ASSERTION 00528 TEXT ASSERTION TEXT ... 00529 00530 --*/ 00531 00532 { 00533 va_list arglist; 00534 UCHAR finalBuffer[512]; 00535 NTSTATUS status; 00536 DC_CHECK_DATA dcCheckData; 00537 PVOID dcParamArray[3*sizeof(DcParamTable)/sizeof(DCPARAM_TYPE_ENTRY)]; 00538 BOOLEAN exitAssertion; 00539 00540 va_start(arglist, MessageParameterMask); 00541 00542 // 00543 // Determine what our basic policy towards this check will be and fill out 00544 // the dcCheckData structure as well as we can. 00545 // 00546 IopDriverCorrectnessProcessParams( 00547 IopDcControlCurrent, 00548 IopDcCurrentFrameSkips, 00549 MessageID, 00550 MessageParameterMask, 00551 &arglist, 00552 dcParamArray, 00553 &dcCheckData 00554 ); 00555 00556 va_end(arglist); 00557 00558 if (!IopDriverCorrectnessApplyControl(&dcCheckData)) { 00559 00560 // 00561 // Nothing to see here, just ignore the assert... 00562 // 00563 return STATUS_SUCCESS; 00564 } 00565 00566 // 00567 // We are going to express our disatifaction somehow. Expand out the 00568 // message we've prepared for this scenario. 00569 // 00570 status = IopDriverCorrectnessProcessMessageText( 00571 sizeof(finalBuffer), 00572 finalBuffer, 00573 &dcCheckData 00574 ); 00575 00576 if (!NT_SUCCESS(status)) { 00577 00578 ASSERT(0); 00579 00580 // 00581 // Something went wrong with the index lookup! 00582 // 00583 return status; 00584 } 00585 00586 do { 00587 00588 IopDriverCorrectnessPrintBuffer(&dcCheckData); 00589 IopDriverCorrectnessPrintParamData(&dcCheckData); 00590 IopDriverCorrectnessThrowBugCheck(&dcCheckData); 00591 IopDriverCorrectnessPrompt(&dcCheckData, &exitAssertion); 00592 00593 } while (!exitAssertion); 00594 00595 return status; 00596 } 00597 00598 VOID 00599 IopDriverCorrectnessProcessParams( 00600 IN OUT PULONG Control OPTIONAL, 00601 IN LONG StackFramesToSkip, 00602 IN DCERROR_ID MessageID, 00603 IN ULONG MessageParameterMask, 00604 IN va_list * MessageParameters, 00605 IN PVOID * DcParamArray, 00606 OUT PDC_CHECK_DATA DcCheckData 00607 ) 00608 { 00609 PVOID returnAddress[1]; 00610 PVOID baseOfImage, culpritAddress; 00611 ULONG stackHash; 00612 PLDR_DATA_TABLE_ENTRY dataTableEntry; 00613 PIMAGE_NT_HEADERS ntHeaders; 00614 ULONG i, currentMessageMask, paramType, maxParameterTypes, paramMask; 00615 ULONG tableIndex; 00616 char ansiDriverName[81]; 00617 00618 tableIndex = MessageID - DCERROR_UNSPECIFIED; 00619 00620 // 00621 // Retrieve a pointer to the appropriate message text. 00622 // 00623 if (tableIndex >= sizeof(IopDcMessageTable)/sizeof(DCERROR_MESSAGE)) { 00624 00625 // 00626 // Bogus message index! 00627 // 00628 ASSERT(0); 00629 tableIndex = 0; 00630 } 00631 00632 ASSERT(IopDcMessageTable[tableIndex].MessageID == MessageID); 00633 00634 // 00635 // OK, we're going to do *something*. Process the incoming parameters. 00636 // 00637 maxParameterTypes = sizeof(DcParamTable)/sizeof(DCPARAM_TYPE_ENTRY); 00638 00639 // 00640 // First we grab parameter off the stack and slot them appropriately into 00641 // our array of "things". 00642 // 00643 // The array is in groups of three for each possible member of a given type 00644 // (three irps, three routines, three device objects, etc). Items not 00645 // referenced in are set to NULL. 00646 // 00647 currentMessageMask = MessageParameterMask; 00648 00649 for(paramType = 0; paramType < maxParameterTypes; paramType++) { 00650 00651 paramMask = DcParamTable[paramType].DcParamMask ; 00652 for(i=0; i<3; i++) { 00653 00654 if (currentMessageMask&(paramMask*3)) { 00655 00656 currentMessageMask -= paramMask; 00657 DcParamArray[paramType*3+i] = va_arg(*MessageParameters, PVOID); 00658 00659 } else { 00660 00661 DcParamArray[paramType*3+i] = NULL; 00662 } 00663 } 00664 } 00665 00666 // 00667 // If this fires, part of the MessageParameterMask was not understood, 00668 // probably a bug by the caller! 00669 // 00670 ASSERT(currentMessageMask == 0); 00671 00672 // 00673 // Pre-init unhelpful answers... 00674 // 00675 culpritAddress = NULL; 00676 DcCheckData->OffsetIntoImage = 0; 00677 DcCheckData->InVerifierList = TRUE; 00678 RtlInitUnicodeString(&DcCheckData->DriverName, NULL); 00679 00680 // 00681 // Blame caller if appropriate 00682 // 00683 if (StackFramesToSkip != -1) { 00684 00685 if (RtlCaptureStackBackTrace(StackFramesToSkip+2, 1, returnAddress, 00686 &stackHash)==1) { 00687 00688 culpritAddress = returnAddress[0]; 00689 } 00690 00691 } else { 00692 00693 // 00694 // %Routine1 00695 // 00696 culpritAddress = DcParamArray[3]; 00697 } 00698 00699 // 00700 // Extract the culprit's name if possible... 00701 // 00702 if (culpritAddress) { 00703 00704 baseOfImage = IopDriverCorrectnessAddressToFileHeader( 00705 (PVOID) culpritAddress, 00706 &dataTableEntry 00707 ); 00708 00709 if (baseOfImage != NULL) { 00710 00711 // 00712 // If we found a match, drill into the dataTableEntry's to get 00713 // 00714 // 00715 if (MmIsAddressValid(dataTableEntry->DllBase) != FALSE) { 00716 00717 ntHeaders = RtlImageNtHeader(dataTableEntry->DllBase); 00718 00719 RtlCopyMemory( 00720 &DcCheckData->DriverName, 00721 &dataTableEntry->BaseDllName, 00722 sizeof(UNICODE_STRING) 00723 ); 00724 00725 DcCheckData->OffsetIntoImage = (PUCHAR) culpritAddress - (PUCHAR) baseOfImage; 00726 } 00727 00728 // 00729 // Now record whether this is in the verifying table. 00730 // 00731 if (!(dataTableEntry->Flags & LDRP_IMAGE_VERIFYING)) { 00732 00733 DcCheckData->InVerifierList = FALSE; 00734 } 00735 } 00736 } 00737 00738 DcCheckData->CulpritAddress = culpritAddress; 00739 DcCheckData->DcParamArray = DcParamArray; 00740 DcCheckData->TableIndex = tableIndex; 00741 DcCheckData->MessageID = MessageID; 00742 DcCheckData->Control = Control; 00743 DcCheckData->AssertionClass = IopDcMessageTable[DcCheckData->TableIndex].MessageClass; 00744 00745 // 00746 // Get an ANSI version of the driver name and root through the override 00747 // table. 00748 // 00749 KeBugCheckUnicodeToAnsi( 00750 &DcCheckData->DriverName, 00751 ansiDriverName, 00752 sizeof(ansiDriverName) 00753 ); 00754 00755 for(i=0; i<sizeof(IopDcOverrideTable)/sizeof(DC_OVERRIDE_TABLE); i++) { 00756 00757 if ((IopDcOverrideTable[i].MessageID == MessageID) || 00758 (IopDcOverrideTable[i].MessageID == DCERROR_UNSPECIFIED)) { 00759 00760 if (!_stricmp(ansiDriverName, IopDcOverrideTable[i].DriverName)) { 00761 00762 // 00763 // We have a match, override the error class. Note that as 00764 // Control is not per-driver, but per assert, we null out 00765 // the passed in Control so that we don't apply this override 00766 // policy against every driver! 00767 // 00768 DcCheckData->Control = NULL; 00769 DcCheckData->AssertionClass = IopDcOverrideTable[i].ReplacementClass; 00770 } 00771 } 00772 } 00773 } 00774 00775 BOOLEAN 00776 IopDriverCorrectnessApplyControl( 00777 IN OUT PDC_CHECK_DATA DcCheckData 00778 ) 00779 { 00780 ULONG assertionControl; 00781 00782 if (IopDcControlOverride) { 00783 00784 assertionControl = IopDcControlOverride; 00785 00786 } else if (DcCheckData->Control) { 00787 00788 // 00789 // Initialize the control if appropo 00790 // 00791 if (!((*DcCheckData->Control)&DIAG_INITIALIZED)) { 00792 00793 *DcCheckData->Control |= ( 00794 DIAG_INITIALIZED | IopDcControlInitial | 00795 DcCheckData->AssertionClass->ClassFlags ); 00796 } 00797 00798 assertionControl = *DcCheckData->Control; 00799 00800 } else { 00801 00802 assertionControl = 00803 ( IopDcControlInitial | DcCheckData->AssertionClass->ClassFlags ); 00804 } 00805 00806 if (assertionControl&DIAG_CLEARED) { 00807 00808 // 00809 // If the breakpoint was cleared, then return, print/rip not. 00810 // 00811 return FALSE; 00812 } 00813 00814 if ((!(assertionControl&DIAG_IGNORE_DRIVER_LIST)) && 00815 (!DcCheckData->InVerifierList)) { 00816 00817 // 00818 // Not of interest, skip this one. 00819 // 00820 return FALSE; 00821 } 00822 00823 // 00824 // If there is no debugger, don't halt the machine. We are probably 00825 // ripping like mad and the user just wants to be able to boot. 00826 // The one exception is if DIAG_FATAL_ERROR is set. Then we shall 00827 // invoke the driver bugcheck... 00828 // 00829 if ((!KdDebuggerEnabled) && (!(assertionControl&DIAG_FATAL_ERROR))) { 00830 00831 return FALSE; 00832 } 00833 00834 // 00835 // Record our intentions and continue. 00836 // 00837 DcCheckData->AssertionControl = assertionControl; 00838 return TRUE; 00839 } 00840 00841 NTSTATUS 00842 IopDriverCorrectnessProcessMessageText( 00843 IN ULONG MaxOutputBufferSize, 00844 OUT PSTR OutputBuffer, 00845 IN OUT PDC_CHECK_DATA DcCheckData 00846 ) 00847 { 00848 ULONG paramType, maxParameterTypes; 00849 ULONG arrayIndex, paramLength; 00850 PSTR messageHead, newMessage; 00851 LONG charsRemaining, length; 00852 00853 // 00854 // Get the message text. 00855 // 00856 messageHead = IopDcMessageTable[DcCheckData->TableIndex].MessageText; 00857 00858 // 00859 // Now manually build out the message. 00860 // 00861 newMessage = OutputBuffer; 00862 charsRemaining = (MaxOutputBufferSize/sizeof(UCHAR))-1; 00863 maxParameterTypes = sizeof(DcParamTable)/sizeof(DCPARAM_TYPE_ENTRY); 00864 00865 while(*messageHead != '\0') { 00866 00867 if (charsRemaining <= 0) { 00868 00869 return STATUS_BUFFER_OVERFLOW; 00870 } 00871 00872 if (*messageHead != '%') { 00873 00874 *newMessage = *messageHead; 00875 newMessage++; 00876 messageHead++; 00877 charsRemaining--; 00878 00879 } else { 00880 00881 for(paramType = 0; paramType < maxParameterTypes; paramType++) { 00882 00883 paramLength = strlen(DcParamTable[paramType].DcParamName); 00884 00885 // 00886 // Do we have a match? 00887 // 00888 // N.B. - We don't do any case 'de-sensitizing' anywhere, so 00889 // everything's cases must match! 00890 // 00891 if (RtlCompareMemory( 00892 messageHead+1, 00893 DcParamTable[paramType].DcParamName, 00894 paramLength*sizeof(UCHAR)) == paramLength*sizeof(UCHAR)) { 00895 00896 arrayIndex = paramType*3; 00897 messageHead += (paramLength+1); 00898 00899 // 00900 // Was an index passed in (ie, "3rd" irp requested)? 00901 // 00902 if ((*messageHead >= '1') && (*messageHead <= '3')) { 00903 00904 // 00905 // Adjust table index appropriately. 00906 // 00907 arrayIndex += (*messageHead - '1') ; 00908 messageHead++; 00909 } 00910 00911 length = _snprintf( 00912 newMessage, 00913 charsRemaining+1, 00914 "%p", 00915 DcCheckData->DcParamArray[arrayIndex] 00916 ); 00917 00918 if (length == -1) { 00919 00920 return STATUS_BUFFER_OVERFLOW; 00921 } 00922 00923 charsRemaining -= length; 00924 newMessage += length; 00925 break; 00926 } 00927 } 00928 00929 if (paramType == maxParameterTypes) { 00930 00931 // 00932 // Either the message we looked up is malformed, we don't recognize 00933 // the %thing it is talking about, or this is %%! 00934 // 00935 *newMessage = *messageHead; 00936 messageHead++; 00937 newMessage++; 00938 charsRemaining--; 00939 00940 if (*messageHead == '%') { 00941 00942 messageHead++; 00943 } 00944 } 00945 } 00946 } 00947 00948 // 00949 // Null-terminate it (we have room because we took one off the buffer size 00950 // above). 00951 // 00952 *newMessage = '\0'; 00953 00954 DcCheckData->ClassText = DcCheckData->AssertionClass->MessageClassText; 00955 DcCheckData->AssertionText = OutputBuffer; 00956 return STATUS_SUCCESS; 00957 } 00958 00959 VOID 00960 IopDriverCorrectnessThrowBugCheck( 00961 IN PDC_CHECK_DATA DcCheckData 00962 ) 00963 { 00964 PVOID parameterArray[4]; 00965 char captionBuffer[256]; 00966 char ansiDriverName[81]; 00967 UNICODE_STRING unicodeString; 00968 00969 // 00970 // Do not bugcheck if a kernel debugger is attached, nor if this isn't a 00971 // fatal error. 00972 // 00973 if (KdDebuggerEnabled || (!(DcCheckData->AssertionControl&DIAG_FATAL_ERROR))) { 00974 00975 return; 00976 } 00977 00978 // 00979 // We are here because DIAG_FATAL_ERROR is set. We use 00980 // FATAL_UNHANDLED_HARD_ERROR so that we can give a 00981 // descriptive text string for the problem. 00982 // 00983 parameterArray[0] = (PVOID) DcCheckData->MessageID; 00984 parameterArray[1] = DcCheckData->CulpritAddress; 00985 parameterArray[2] = DcCheckData->DcParamArray[0]; 00986 parameterArray[3] = DcCheckData->DcParamArray[6]; 00987 00988 KeBugCheckUnicodeToAnsi( 00989 &DcCheckData->DriverName, 00990 ansiDriverName, 00991 sizeof(ansiDriverName) 00992 ); 00993 00994 _snprintf( 00995 captionBuffer, 00996 sizeof(captionBuffer), 00997 "IO SYSTEM VERIFICATION ERROR in %s (%s %x)\n[%s+%x at %p]\n", 00998 ansiDriverName, 00999 DcCheckData->ClassText, 01000 DcCheckData->MessageID, 01001 ansiDriverName, 01002 DcCheckData->OffsetIntoImage, 01003 DcCheckData->CulpritAddress 01004 ); 01005 01006 KeBugCheckEx( 01007 FATAL_UNHANDLED_HARD_ERROR, 01008 DRIVER_VERIFIER_IOMANAGER_VIOLATION, 01009 (ULONG_PTR) parameterArray, 01010 (ULONG_PTR) captionBuffer, 01011 (ULONG_PTR) "" // DcCheckData->AssertionText is too technical 01012 ); 01013 } 01014 01015 VOID 01016 IopDriverCorrectnessPrintBuffer( 01017 IN PDC_CHECK_DATA DcCheckData 01018 ) 01019 { 01020 UCHAR buffer[82]; 01021 UCHAR classBuf[81]; 01022 UCHAR callerBuf[81+40]; 01023 UCHAR ansiDriverName[81]; 01024 LONG lMargin, i, lMarginCur, rMargin=78; 01025 PSTR lineStart, lastWord, current, lMarginText; 01026 01027 // 01028 // Put down a carraige return 01029 // 01030 DbgPrint("\n") ; 01031 01032 // 01033 // Drop a banner if this is a fatal assert. 01034 // 01035 if (DcCheckData->AssertionControl&DIAG_FATAL_ERROR) { 01036 01037 DbgPrint( 01038 "***********************************************************************\n" 01039 "* THIS DRIVER BUG IS FATAL AND WILL CAUSE THE VERIFIER TO HALT *\n" 01040 "* WINDOWS (BUGCHECK) WHEN THE MACHINE IS NOT UNDER A KERNEL DEBUGGER! *\n" 01041 "***********************************************************************\n" 01042 "\n" 01043 ); 01044 } 01045 01046 // 01047 // Prepare left margin (ClassText) 01048 // 01049 if (DcCheckData->ClassText != NULL) { 01050 01051 lMargin = strlen(DcCheckData->ClassText)+2; 01052 01053 DbgPrint("%s: ", DcCheckData->ClassText); 01054 01055 } else { 01056 01057 lMargin = 0; 01058 } 01059 01060 if (lMargin+1>=rMargin) { 01061 01062 lMargin=0; 01063 } 01064 01065 for(i=0; i<lMargin; i++) classBuf[i] = ' '; 01066 classBuf[lMargin] = '\0'; 01067 lMarginText = classBuf+lMargin; 01068 lMarginCur = lMargin; 01069 01070 lineStart = lastWord = current = DcCheckData->AssertionText; 01071 01072 // 01073 // Print out culprit if we have him... 01074 // 01075 if (DcCheckData->CulpritAddress) { 01076 01077 if (DcCheckData->DriverName.Length) { 01078 01079 KeBugCheckUnicodeToAnsi( 01080 &DcCheckData->DriverName, 01081 ansiDriverName, 01082 sizeof(ansiDriverName) 01083 ); 01084 01085 sprintf(callerBuf, "[%s @ 0x%p] ", 01086 ansiDriverName, 01087 DcCheckData->CulpritAddress 01088 ); 01089 01090 } else { 01091 01092 sprintf(callerBuf, "[0x%p] ", DcCheckData->CulpritAddress); 01093 } 01094 01095 DbgPrint("%s", callerBuf); 01096 lMarginCur += strlen(callerBuf); 01097 } 01098 01099 // 01100 // Format and print our assertion text 01101 // 01102 while(*current) { 01103 01104 if (*current == ' ') { 01105 01106 if ((current - lineStart) >= (rMargin-lMarginCur-1)) { 01107 01108 DbgPrint("%s", lMarginText); 01109 lMarginText = classBuf; 01110 lMarginCur = lMargin; 01111 01112 if ((lastWord-lineStart)<rMargin) { 01113 01114 memcpy(buffer, lineStart, (ULONG)(lastWord-lineStart)*sizeof(UCHAR)); 01115 buffer[lastWord-lineStart] = '\0'; 01116 DbgPrint("%s\n", buffer); 01117 01118 } 01119 01120 lineStart = lastWord+1; 01121 } 01122 01123 lastWord = current; 01124 } 01125 01126 current++; 01127 } 01128 01129 if ((current - lineStart) >= (rMargin-lMarginCur-1)) { 01130 01131 DbgPrint("%s", lMarginText); 01132 lMarginText = classBuf; 01133 01134 if ((lastWord-lineStart)<rMargin) { 01135 01136 memcpy(buffer, lineStart, (ULONG)(lastWord-lineStart)*sizeof(UCHAR)); 01137 buffer[lastWord-lineStart] = '\0'; 01138 DbgPrint("%s\n", buffer); 01139 } 01140 01141 lineStart = lastWord+1; 01142 } 01143 01144 if (lineStart<current) { 01145 01146 DbgPrint("%s%s\n", lMarginText, lineStart); 01147 } 01148 } 01149 01150 VOID 01151 IopDriverCorrectnessPrintParamData( 01152 IN PDC_CHECK_DATA DcCheckData 01153 ) 01154 { 01155 if (DcCheckData->DcParamArray[0]) { 01156 01157 IopDriverCorrectnessPrintIrp((PIRP) DcCheckData->DcParamArray[0]); 01158 } 01159 } 01160 01161 VOID 01162 IopDriverCorrectnessPrompt( 01163 IN PDC_CHECK_DATA DcCheckData, 01164 OUT PBOOLEAN ExitAssertion 01165 ) 01166 { 01167 char response[2]; 01168 ULONG assertionControl; 01169 BOOLEAN waitForInput; 01170 01171 assertionControl = DcCheckData->AssertionControl; 01172 01173 *ExitAssertion = TRUE; 01174 01175 // 01176 // Vocalize if so ordered. 01177 // 01178 if (assertionControl&DIAG_BEEP) { 01179 01180 DbgPrint("%c", 7); 01181 } 01182 01183 if (assertionControl&DIAG_ZAPPED) { 01184 01185 return; 01186 } 01187 01188 // 01189 // Wait for input... 01190 // 01191 waitForInput = TRUE; 01192 while(waitForInput) { 01193 01194 if (DcCheckData->Control) { 01195 01196 DbgPrompt( "Break, Ignore, Zap, Remove, Disable all (bizrd)? ", response, sizeof( response )); 01197 } else { 01198 01199 DbgPrompt( "Break, Ignore, Disable all (bid)? ", response, sizeof( response )); 01200 } 01201 01202 switch (response[0]) { 01203 01204 case 'B': 01205 case 'b': 01206 DbgPrint("Breaking in... (press g<enter> to return to assert menu)\n"); 01207 DbgBreakPoint(); 01208 waitForInput = FALSE; 01209 *ExitAssertion = FALSE; 01210 break; 01211 01212 case 'I': 01213 case 'i': 01214 waitForInput = FALSE; 01215 break; 01216 01217 case 'Z': 01218 case 'z': 01219 if (DcCheckData->Control) { 01220 01221 DbgPrint("Breakpoint zapped (OS will print text and return)\n"); 01222 assertionControl |= DIAG_ZAPPED; 01223 assertionControl &=~ DIAG_BEEP; 01224 waitForInput = FALSE; 01225 } 01226 break; 01227 01228 case 'D': 01229 case 'd': 01230 IopDcControlOverride = DIAG_CLEARED; 01231 DbgPrint("Verification asserts disabled.\n"); 01232 //assertionControl |= DIAG_CLEARED; 01233 waitForInput = FALSE; 01234 break; 01235 01236 case 'R': 01237 case 'r': 01238 if (DcCheckData->Control) { 01239 01240 DbgPrint("Breakpoint removed\n") ; 01241 assertionControl |= DIAG_CLEARED; 01242 waitForInput = FALSE; 01243 } 01244 break; 01245 } 01246 } 01247 01248 if (DcCheckData->Control) { 01249 *DcCheckData->Control = assertionControl; 01250 } 01251 } 01252 01253 PVOID 01254 IopDriverCorrectnessAddressToFileHeader( 01255 IN PVOID Address, 01256 OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry 01257 ) 01258 01259 /*++ 01260 01261 Routine Description: 01262 01263 This function returns the base of an image that contains the 01264 specified Address. An image contains the address if the address 01265 is within the ImageBase, and the ImageBase plus the size of the 01266 virtual image. 01267 01268 Arguments: 01269 01270 Address - Supplies an address to resolve to a loader entry. 01271 01272 DataTableEntry - Suppies a pointer to a variable that receives the 01273 address of the data table entry that describes the image. 01274 01275 Return Value: 01276 01277 NULL - No image was found that contains the passed in address. 01278 01279 NON-NULL - Returns the base address of the image that contain the 01280 address. 01281 01282 --*/ 01283 01284 { 01285 01286 PLIST_ENTRY ModuleListHead; 01287 PLDR_DATA_TABLE_ENTRY Entry; 01288 PLIST_ENTRY Next; 01289 UINT_PTR Bounds; 01290 PVOID ReturnBase=NULL, Base; 01291 01292 ModuleListHead = &PsLoadedModuleList; 01293 01294 // 01295 // It would be nice if we could call MiLookupDataTableEntry, but it's 01296 // pageable, so we do what the bugcheck stuff does... 01297 // 01298 Next = ModuleListHead->Flink; 01299 if (Next != NULL) { 01300 while (Next != ModuleListHead) { 01301 Entry = CONTAINING_RECORD(Next, 01302 LDR_DATA_TABLE_ENTRY, 01303 InLoadOrderLinks); 01304 01305 Next = Next->Flink; 01306 Base = Entry->DllBase; 01307 Bounds = (UINT_PTR)Base + Entry->SizeOfImage; 01308 if ((UINT_PTR)Address >= (UINT_PTR)Base && (UINT_PTR)Address < Bounds) { 01309 *DataTableEntry = Entry; 01310 ReturnBase = Base; 01311 break; 01312 } 01313 } 01314 } 01315 01316 return ReturnBase; 01317 } 01318 01319 BOOLEAN 01320 IopIsMemoryRangeReadable( 01321 IN PVOID Location, 01322 IN size_t Length 01323 ) 01324 { 01325 while (((ULONG_PTR)Location & (sizeof(ULONG_PTR)-1)) && (Length > 0)) { 01326 01327 // 01328 // Check to determine if the move will succeed before actually performing 01329 // the operation. 01330 // 01331 if (MmIsAddressValid(Location)==FALSE) { 01332 return FALSE ; 01333 } 01334 01335 ((PCHAR) Location)++ ; 01336 Length-- ; 01337 } 01338 01339 while (Length > (sizeof(ULONG_PTR)-1)) { 01340 01341 // 01342 // Check to determine if the move will succeed before actually performing 01343 // the operation. 01344 // 01345 if (MmIsAddressValid(Location)==FALSE) { 01346 return FALSE ; 01347 } 01348 ((PCHAR) Location) += sizeof(ULONG_PTR); 01349 Length -= sizeof(ULONG_PTR); 01350 01351 } 01352 01353 while (Length > 0) { 01354 01355 // 01356 // Check to determine if the move will succeed before actually performing 01357 // the operation. 01358 // 01359 if (MmIsAddressValid(Location)==FALSE) { 01360 return FALSE; 01361 } 01362 01363 ((PCHAR) Location)++ ; 01364 Length-- ; 01365 } 01366 return TRUE ; 01367 } 01368 01369 VOID 01370 IopDriverCorrectnessPrintIrp( 01371 IN PIRP IrpToFlag 01372 ) 01373 { 01374 PIO_STACK_LOCATION irpSpCur ; 01375 PIO_STACK_LOCATION irpSpNxt ; 01376 01377 // 01378 // First see if we can touch the IRP header 01379 // 01380 if(!IopIsMemoryRangeReadable(IrpToFlag, sizeof(IRP))) { 01381 return ; 01382 } 01383 01384 // 01385 // OK, get the next two stack locations... 01386 // 01387 irpSpNxt = IoGetNextIrpStackLocation( IrpToFlag ); 01388 irpSpCur = IoGetCurrentIrpStackLocation( IrpToFlag ); 01389 01390 if (IopIsMemoryRangeReadable(irpSpNxt, 2*sizeof(IO_STACK_LOCATION))) { 01391 01392 // 01393 // Both are present, print the best one! 01394 // 01395 if (irpSpNxt->MinorFunction == irpSpCur->MinorFunction) { 01396 01397 // 01398 // Looks forwarded 01399 // 01400 IopDriverCorrectnessPrintIrpStack(irpSpNxt) ; 01401 } else if (irpSpNxt->MinorFunction == 0) { 01402 01403 // 01404 // Next location is probably currently zero'd 01405 // 01406 IopDriverCorrectnessPrintIrpStack(irpSpCur) ; 01407 } else { 01408 DbgPrint("Next: >") ; 01409 IopDriverCorrectnessPrintIrpStack(irpSpNxt) ; 01410 DbgPrint("Current: ") ; 01411 IopDriverCorrectnessPrintIrpStack(irpSpCur) ; 01412 } 01413 } else if (IopIsMemoryRangeReadable(irpSpCur, sizeof(IO_STACK_LOCATION))) { 01414 01415 IopDriverCorrectnessPrintIrpStack(irpSpCur) ; 01416 } else if (IopIsMemoryRangeReadable(irpSpNxt, sizeof(IO_STACK_LOCATION))) { 01417 01418 IopDriverCorrectnessPrintIrpStack(irpSpNxt) ; 01419 } 01420 } 01421 01422 PCHAR IrpMajorNames[] = { 01423 "IRP_MJ_CREATE", // 0x00 01424 "IRP_MJ_CREATE_NAMED_PIPE", // 0x01 01425 "IRP_MJ_CLOSE", // 0x02 01426 "IRP_MJ_READ", // 0x03 01427 "IRP_MJ_WRITE", // 0x04 01428 "IRP_MJ_QUERY_INFORMATION", // 0x05 01429 "IRP_MJ_SET_INFORMATION", // 0x06 01430 "IRP_MJ_QUERY_EA", // 0x07 01431 "IRP_MJ_SET_EA", // 0x08 01432 "IRP_MJ_FLUSH_BUFFERS", // 0x09 01433 "IRP_MJ_QUERY_VOLUME_INFORMATION", // 0x0a 01434 "IRP_MJ_SET_VOLUME_INFORMATION", // 0x0b 01435 "IRP_MJ_DIRECTORY_CONTROL", // 0x0c 01436 "IRP_MJ_FILE_SYSTEM_CONTROL", // 0x0d 01437 "IRP_MJ_DEVICE_CONTROL", // 0x0e 01438 "IRP_MJ_INTERNAL_DEVICE_CONTROL", // 0x0f 01439 "IRP_MJ_SHUTDOWN", // 0x10 01440 "IRP_MJ_LOCK_CONTROL", // 0x11 01441 "IRP_MJ_CLEANUP", // 0x12 01442 "IRP_MJ_CREATE_MAILSLOT", // 0x13 01443 "IRP_MJ_QUERY_SECURITY", // 0x14 01444 "IRP_MJ_SET_SECURITY", // 0x15 01445 "IRP_MJ_POWER", // 0x16 01446 "IRP_MJ_SYSTEM_CONTROL", // 0x17 01447 "IRP_MJ_DEVICE_CHANGE", // 0x18 01448 "IRP_MJ_QUERY_QUOTA", // 0x19 01449 "IRP_MJ_SET_QUOTA", // 0x1a 01450 "IRP_MJ_PNP", // 0x1b 01451 NULL 01452 } ; 01453 01454 #define MAX_NAMED_MAJOR_IRPS 0x1b 01455 01456 01457 PCHAR PnPIrpNames[] = { 01458 "IRP_MN_START_DEVICE", // 0x00 01459 "IRP_MN_QUERY_REMOVE_DEVICE", // 0x01 01460 "IRP_MN_REMOVE_DEVICE - ", // 0x02 01461 "IRP_MN_CANCEL_REMOVE_DEVICE", // 0x03 01462 "IRP_MN_STOP_DEVICE", // 0x04 01463 "IRP_MN_QUERY_STOP_DEVICE", // 0x05 01464 "IRP_MN_CANCEL_STOP_DEVICE", // 0x06 01465 "IRP_MN_QUERY_DEVICE_RELATIONS", // 0x07 01466 "IRP_MN_QUERY_INTERFACE", // 0x08 01467 "IRP_MN_QUERY_CAPABILITIES", // 0x09 01468 "IRP_MN_QUERY_RESOURCES", // 0x0A 01469 "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", // 0x0B 01470 "IRP_MN_QUERY_DEVICE_TEXT", // 0x0C 01471 "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", // 0x0D 01472 "INVALID_IRP_CODE", // 01473 "IRP_MN_READ_CONFIG", // 0x0F 01474 "IRP_MN_WRITE_CONFIG", // 0x10 01475 "IRP_MN_EJECT", // 0x11 01476 "IRP_MN_SET_LOCK", // 0x12 01477 "IRP_MN_QUERY_ID", // 0x13 01478 "IRP_MN_QUERY_PNP_DEVICE_STATE", // 0x14 01479 "IRP_MN_QUERY_BUS_INFORMATION", // 0x15 01480 "IRP_MN_DEVICE_USAGE_NOTIFICATION", // 0x16 01481 "IRP_MN_SURPRISE_REMOVAL", // 0x17 01482 "IRP_MN_QUERY_LEGACY_BUS_INFORMATION", // 0x18 01483 NULL 01484 } ; 01485 01486 #define MAX_NAMED_PNP_IRP 0x18 01487 01488 PCHAR WmiIrpNames[] = { 01489 "IRP_MN_QUERY_ALL_DATA", // 0x00 01490 "IRP_MN_QUERY_SINGLE_INSTANCE", // 0x01 01491 "IRP_MN_CHANGE_SINGLE_INSTANCE", // 0x02 01492 "IRP_MN_CHANGE_SINGLE_ITEM", // 0x03 01493 "IRP_MN_ENABLE_EVENTS", // 0x04 01494 "IRP_MN_DISABLE_EVENTS", // 0x05 01495 "IRP_MN_ENABLE_COLLECTION", // 0x06 01496 "IRP_MN_DISABLE_COLLECTION", // 0x07 01497 "IRP_MN_REGINFO", // 0x08 01498 "IRP_MN_EXECUTE_METHOD", // 0x09 01499 NULL 01500 } ; 01501 01502 #define MAX_NAMED_WMI_IRP 0x9 01503 01504 PCHAR PowerIrpNames[] = { 01505 "IRP_MN_WAIT_WAKE", // 0x00 01506 "IRP_MN_POWER_SEQUENCE", // 0x01 01507 "IRP_MN_SET_POWER", // 0x02 01508 "IRP_MN_QUERY_POWER", // 0x03 01509 NULL 01510 } ; 01511 01512 #define MAX_NAMED_POWER_IRP 0x3 01513 01514 01515 VOID 01516 IopDriverCorrectnessPrintIrpStack( 01517 IN PIO_STACK_LOCATION IrpSp 01518 ) 01519 { 01520 if ((IrpSp->MajorFunction==IRP_MJ_INTERNAL_DEVICE_CONTROL)&&(IrpSp->MinorFunction == IRP_MN_SCSI_CLASS)) { 01521 01522 DbgPrint("IRP_MJ_SCSI") ; 01523 01524 } else if (IrpSp->MajorFunction<=MAX_NAMED_MAJOR_IRPS) { 01525 01526 DbgPrint(IrpMajorNames[IrpSp->MajorFunction]) ; 01527 01528 } else if (IrpSp->MajorFunction==0xFF) { 01529 01530 DbgPrint("IRP_MJ_BOGUS") ; 01531 01532 } else { 01533 01534 DbgPrint("IRP_MJ_??") ; 01535 } 01536 01537 switch(IrpSp->MajorFunction) { 01538 01539 case IRP_MJ_SYSTEM_CONTROL: 01540 DbgPrint(".") ; 01541 if (IrpSp->MinorFunction<=MAX_NAMED_WMI_IRP) { 01542 01543 DbgPrint(WmiIrpNames[IrpSp->MinorFunction]) ; 01544 } else if (IrpSp->MinorFunction==0xFF) { 01545 01546 DbgPrint("IRP_MN_BOGUS") ; 01547 } else { 01548 DbgPrint("(Bogus)\n") ; 01549 } 01550 DbgPrint("\n") ; 01551 break ; 01552 case IRP_MJ_PNP: 01553 DbgPrint(".") ; 01554 if (IrpSp->MinorFunction<=MAX_NAMED_PNP_IRP) { 01555 01556 DbgPrint(PnPIrpNames[IrpSp->MinorFunction]) ; 01557 } else if (IrpSp->MinorFunction==0xFF) { 01558 01559 DbgPrint("IRP_MN_BOGUS") ; 01560 } else { 01561 01562 DbgPrint("(Bogus)\n") ; 01563 } 01564 switch(IrpSp->MinorFunction) { 01565 case IRP_MN_QUERY_DEVICE_RELATIONS: 01566 01567 switch(IrpSp->Parameters.QueryDeviceRelations.Type) { 01568 case BusRelations: 01569 DbgPrint("(BusRelations)") ; 01570 break ; 01571 case EjectionRelations: 01572 DbgPrint("(EjectionRelations)") ; 01573 break ; 01574 case PowerRelations: 01575 DbgPrint("(PowerRelations)") ; 01576 break ; 01577 case RemovalRelations: 01578 DbgPrint("(RemovalRelations)") ; 01579 break ; 01580 case TargetDeviceRelation: 01581 DbgPrint("(TargetDeviceRelation)") ; 01582 break ; 01583 default: 01584 DbgPrint("(Bogus)\n") ; 01585 break ; 01586 } 01587 break ; 01588 case IRP_MN_QUERY_INTERFACE: 01589 break ; 01590 case IRP_MN_QUERY_DEVICE_TEXT: 01591 switch(IrpSp->Parameters.QueryId.IdType) { 01592 case DeviceTextDescription: 01593 DbgPrint("(DeviceTextDescription)") ; 01594 break ; 01595 case DeviceTextLocationInformation: 01596 DbgPrint("(DeviceTextLocationInformation)") ; 01597 break ; 01598 default: 01599 DbgPrint("(Bogus)\n") ; 01600 break ; 01601 } 01602 break ; 01603 case IRP_MN_WRITE_CONFIG: 01604 case IRP_MN_READ_CONFIG: 01605 DbgPrint("(WhichSpace=%x, Buffer=%x, Offset=%x, Length=%x)", 01606 IrpSp->Parameters.ReadWriteConfig.WhichSpace, 01607 IrpSp->Parameters.ReadWriteConfig.Buffer, 01608 IrpSp->Parameters.ReadWriteConfig.Offset, 01609 IrpSp->Parameters.ReadWriteConfig.Length 01610 ) ; 01611 break ; 01612 case IRP_MN_SET_LOCK: 01613 if (IrpSp->Parameters.SetLock.Lock) DbgPrint("(True)") ; 01614 else DbgPrint("(False)") ; 01615 break ; 01616 case IRP_MN_QUERY_ID: 01617 switch(IrpSp->Parameters.QueryId.IdType) { 01618 case BusQueryDeviceID: 01619 DbgPrint("(BusQueryDeviceID)") ; 01620 break ; 01621 case BusQueryHardwareIDs: 01622 DbgPrint("(BusQueryHardwareIDs)") ; 01623 break ; 01624 case BusQueryCompatibleIDs: 01625 DbgPrint("(BusQueryCompatibleIDs)") ; 01626 break ; 01627 case BusQueryInstanceID: 01628 DbgPrint("(BusQueryInstanceID)") ; 01629 break ; 01630 default: 01631 DbgPrint("(Bogus)\n") ; 01632 break ; 01633 } 01634 break ; 01635 case IRP_MN_QUERY_BUS_INFORMATION: 01636 // BUGBUG: Should print out 01637 break ; 01638 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 01639 switch(IrpSp->Parameters.UsageNotification.Type) { 01640 case DeviceUsageTypeUndefined: 01641 DbgPrint("(DeviceUsageTypeUndefined") ; 01642 break ; 01643 case DeviceUsageTypePaging: 01644 DbgPrint("(DeviceUsageTypePaging") ; 01645 break ; 01646 case DeviceUsageTypeHibernation: 01647 DbgPrint("(DeviceUsageTypeHibernation") ; 01648 break ; 01649 case DeviceUsageTypeDumpFile: 01650 DbgPrint("(DeviceUsageTypeDumpFile") ; 01651 break ; 01652 default: 01653 DbgPrint("(Bogus)\n") ; 01654 break ; 01655 } 01656 if (IrpSp->Parameters.UsageNotification.InPath) { 01657 DbgPrint(", InPath=TRUE)") ; 01658 } else { 01659 DbgPrint(", InPath=FALSE)") ; 01660 } 01661 break ; 01662 case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: 01663 // BUGBUG: Should print out 01664 break ; 01665 default: 01666 break ; 01667 } 01668 DbgPrint("\n") ; 01669 break ; 01670 01671 case IRP_MJ_POWER: 01672 DbgPrint(".") ; 01673 if (IrpSp->MinorFunction<=MAX_NAMED_POWER_IRP) { 01674 01675 DbgPrint(PowerIrpNames[IrpSp->MinorFunction]) ; 01676 } else if (IrpSp->MinorFunction==0xFF) { 01677 01678 DbgPrint("IRP_MN_BOGUS") ; 01679 } else { 01680 DbgPrint("(Bogus)\n") ; 01681 } 01682 DbgPrint("\n") ; 01683 break ; 01684 01685 default: 01686 DbgPrint("\n") ; 01687 break ; 01688 } 01689 } 01690 #endif // NO_SPECIAL_IRP 01691

Generated on Sat May 15 19:40:28 2004 for test by doxygen 1.3.7