00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 Filter.c 00008 00009 Abstract: 00010 00011 The Exception filter is used by the file system and cache manager 00012 to handle error recovery. The basic idea is to have the top level 00013 file system entry points (i.e., the FSD entry points and FSP dispatch 00014 loop) have a try-except around their code, and then whenever the 00015 file system or cache manager reach an error case they raise an 00016 appropriate status. Then the exception handler catches the exception 00017 and can either complete the request, send it off to the fsp, verify the 00018 volume, or bugcheck. We only bugcheck if the raised exception is 00019 unexpected (i.e., unhandled). 00020 00021 This module provides two routines for filtering out exceptions. The 00022 first routine is used to normalize status values to be one of the 00023 value handled by the filter. That way if we get an exception not handled 00024 by the filter then we know that the system is in real trouble and we 00025 just bugcheck the machine. The second routine is used to ask if 00026 a status value is within the set of values handled by the filter. 00027 00028 The value of status handled by this filter are listed in the routine 00029 FsRtlIsNtstatusExpected. 00030 00031 Author: 00032 00033 Gary Kimura [GaryKi] 4-Jan-1991 00034 00035 Revision History: 00036 00037 --*/ 00038 00039 #include "FsRtlP.h" 00040 00041 // 00042 // Trace level for the module 00043 // 00044 00045 #define Dbg (0x80000000) 00046 00047 00048 NTSTATUS 00049 FsRtlNormalizeNtstatus ( 00050 IN NTSTATUS Exception, 00051 IN NTSTATUS GenericException 00052 ) 00053 00054 /*++ 00055 00056 Routine Description: 00057 00058 This routine is used to normalize an NTSTATUS into a status 00059 that is handled by the file system's top level exception handlers. 00060 00061 Arguments: 00062 00063 Exception - Supplies the exception being normalized 00064 00065 GenericException - Supplies a second exception to translate to 00066 if the first exception is not within the set of exceptions 00067 handled by the filter 00068 00069 Return Value: 00070 00071 NTSTATUS - Returns Exception if the value is already handled 00072 by the filter, and GenericException otherwise. 00073 00074 --*/ 00075 00076 { 00077 return (FsRtlIsNtstatusExpected(Exception) ? Exception : GenericException); 00078 } 00079 00080 00081 BOOLEAN 00082 FsRtlIsNtstatusExpected ( 00083 IN NTSTATUS Exception 00084 ) 00085 00086 /*++ 00087 00088 Routine Description: 00089 00090 This routine is used to decide if a status is within the set of values 00091 handled by the exception filter. 00092 00093 Arguments: 00094 00095 Exception - Supplies the exception being queried 00096 00097 Return Value: 00098 00099 BOOLEAN - Returns TRUE if the value is handled by the filter, and 00100 FALSE otherwise. 00101 00102 --*/ 00103 00104 { 00105 switch (Exception) { 00106 00107 case STATUS_DATATYPE_MISALIGNMENT: 00108 case STATUS_ACCESS_VIOLATION: 00109 case STATUS_ILLEGAL_INSTRUCTION: 00110 case STATUS_INSTRUCTION_MISALIGNMENT: 00111 00112 return FALSE; 00113 00114 default: 00115 00116 return TRUE; 00117 } 00118 } 00119 00120 00121 #undef FsRtlAllocatePool 00122 00123 PVOID 00124 FsRtlAllocatePool ( 00125 IN POOL_TYPE PoolType, 00126 IN ULONG NumberOfBytes 00127 ) 00128 00129 /*++ 00130 00131 Routine Description: 00132 00133 This routine is used to allocate executive level pool. It either 00134 returns a non null pointer to the newly allocated pool or it raises 00135 a status of insufficient resources. 00136 00137 Arguments: 00138 00139 PoolType - Supplies the type of executive pool to allocate 00140 00141 NumberOfBytes - Supplies the number of bytes to allocate 00142 00143 Return Value: 00144 00145 PVOID - Returns a non null pointer to the newly allocated pool. 00146 00147 --*/ 00148 00149 { 00150 PVOID p; 00151 00152 // 00153 // Allocate executive pool and if we get back null then raise 00154 // a status of insufficient resources 00155 // 00156 00157 if ((p = ExAllocatePoolWithTag( PoolType, NumberOfBytes, 'trSF')) == NULL) { 00158 00159 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00160 } 00161 00162 return p; 00163 } 00164 00165 #undef FsRtlAllocatePoolWithQuota 00166 00167 00168 PVOID 00169 FsRtlAllocatePoolWithQuota ( 00170 IN POOL_TYPE PoolType, 00171 IN ULONG NumberOfBytes 00172 ) 00173 00174 /*++ 00175 00176 Routine Description: 00177 00178 This routine is used to allocate executive level pool with quota. It 00179 either returns a non null pointer to the newly allocated pool or it raises 00180 a status of insufficient resources. 00181 00182 Arguments: 00183 00184 PoolType - Supplies the type of executive pool to allocate 00185 00186 NumberOfBytes - Supplies the number of bytes to allocate 00187 00188 Return Value: 00189 00190 PVOID - Returns a non null pointer to the newly allocated pool. 00191 00192 --*/ 00193 00194 { 00195 PVOID p; 00196 00197 // 00198 // Allocate executive pool and if we get back null then raise 00199 // a status of insufficient resources 00200 // 00201 00202 if ((p = ExAllocatePoolWithQuotaTag ( PoolType, NumberOfBytes, 'trSF')) == NULL) { 00203 00204 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00205 } 00206 00207 return p; 00208 } 00209 00210 00211 #undef FsRtlAllocatePoolWithTag 00212 00213 PVOID 00214 FsRtlAllocatePoolWithTag ( 00215 IN POOL_TYPE PoolType, 00216 IN ULONG NumberOfBytes, 00217 IN ULONG Tag 00218 ) 00219 00220 /*++ 00221 00222 Routine Description: 00223 00224 This routine is used to allocate executive level pool with a tag. 00225 00226 Arguments: 00227 00228 PoolType - Supplies the type of executive pool to allocate 00229 00230 NumberOfBytes - Supplies the number of bytes to allocate 00231 00232 Tag - Supplies the tag for the pool block 00233 00234 Return Value: 00235 00236 PVOID - Returns a non null pointer to the newly allocated pool. 00237 00238 --*/ 00239 00240 { 00241 PVOID p; 00242 00243 // 00244 // Allocate executive pool and if we get back null then raise 00245 // a status of insufficient resources 00246 // 00247 00248 if ((p = ExAllocatePoolWithTag( PoolType, NumberOfBytes, Tag)) == NULL) { 00249 00250 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00251 } 00252 00253 return p; 00254 } 00255 00256 00257 #undef FsRtlAllocatePoolWithQuotaTag 00258 00259 PVOID 00260 FsRtlAllocatePoolWithQuotaTag ( 00261 IN POOL_TYPE PoolType, 00262 IN ULONG NumberOfBytes, 00263 IN ULONG Tag 00264 ) 00265 00266 /*++ 00267 00268 Routine Description: 00269 00270 This routine is used to allocate executive level pool with a quota tag. 00271 00272 Arguments: 00273 00274 PoolType - Supplies the type of executive pool to allocate 00275 00276 NumberOfBytes - Supplies the number of bytes to allocate 00277 00278 Tag - Supplies the tag for the pool block 00279 00280 Return Value: 00281 00282 PVOID - Returns a non null pointer to the newly allocated pool. 00283 00284 --*/ 00285 00286 { 00287 PVOID p; 00288 00289 // 00290 // Allocate executive pool and if we get back null then raise 00291 // a status of insufficient resources 00292 // 00293 00294 if ((p = ExAllocatePoolWithQuotaTag( PoolType, NumberOfBytes, Tag)) == NULL) { 00295 00296 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00297 } 00298 00299 return p; 00300 } 00301 00302 00303 BOOLEAN 00304 FsRtlIsTotalDeviceFailure( 00305 IN NTSTATUS Status 00306 ) 00307 00308 /*++ 00309 00310 Routine Description: 00311 00312 This routine is given an NTSTATUS value and make a determination as to 00313 if this value indicates that the complete device has failed and therefore 00314 should no longer be used, or if the failure is one that indicates that 00315 continued use of the device is ok (i.e. a sector failure). 00316 00317 Arguments: 00318 00319 Status - the NTSTATUS value to test. 00320 00321 Return Value: 00322 00323 TRUE - The status value given is believed to be a fatal device error. 00324 FALSE - The status value given is believed to be a sector failure, but not 00325 a complete device failure. 00326 --*/ 00327 00328 { 00329 if (NT_SUCCESS(Status)) { 00330 00331 // 00332 // All warning and informational errors will be resolved here. 00333 // 00334 00335 return FALSE; 00336 } 00337 00338 switch (Status) { 00339 case STATUS_CRC_ERROR: 00340 case STATUS_DEVICE_DATA_ERROR: 00341 return FALSE; 00342 default: 00343 return TRUE; 00344 } 00345 }