GetExceptionCode

[Previous] [Next]

Often an exception filter must analyze the situation before it can determine which value to return. For example, your handler might know what to do if a divide by 0 exception occurs, but it might not know how to handle a memory access exception. The exception filter has the responsibility for examining the situation and returning the appropriate value.

This code demonstrates a method for identifying the kind of exception that has occurred:

 _ _try { x = 0; y = 4 / x; } _ _except ((GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { // Handle divide by zero exception. } 

The GetExceptionCode intrinsic function returns a value identifying the kind of exception that has occurred:

 DWORD GetExceptionCode(); 

The following list of all predefined exceptions and their meanings is adapted from the Platform SDK documentation. The exception identifiers can be found in the WinBase.h file. I have grouped the exceptions together by category.

Memory-Related Exceptions

  • EXCEPTION_ACCESS_VIOLATION The thread tried to read from or write to a virtual address for which it doesn't have the appropriate access. This is the most common exception.
  • EXCEPTION_DATATYPE_MISALIGNMENT The thread tried to read or write data that is misaligned on hardware that doesn't provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries, 32-bit values on 4-byte boundaries, and so on.
  • EXCEPTION_ARRAY_BOUNDS_EXCEEDED The thread tried to access an array element that is out of bounds, and the underlying hardware supports bounds checking.
  • EXCEPTION_IN_PAGE_ERROR A page fault couldn't be satisfied because the file system or a device driver returned a read error.
  • EXCEPTION_GUARD_PAGE A thread attempted to access a page of memory that has the PAGE_GUARD protection attribute. The page is made accessible, and an EXCEPTION_GUARD_PAGE exception is raised.
  • EXCEPTION_STACK_OVERFLOW The thread has used all of its allotted stack.
  • EXCEPTION_ILLEGAL_INSTRUCTION A thread executed an invalid instruction. This exception is defined by the specific CPU architecture; executing an invalid instruction can cause a trap error on different CPUs.
  • EXCEPTION_PRIV_INSTRUCTION The thread tried to execute an instruction whose operation is not allowed in the current machine mode.

Exception-Related Exceptions

  • EXCEPTION_INVALID_DISPOSITION An exception filter returned a value other than EXCEPTION_EXECUTE_HANDLER, EXCEPTION_CONTINUE_SEARCH, or EXCEPTION_CONTINUE_EXECUTION.
  • EXCEPTION_NONCONTINUABLE_EXCEPTION An exception filter returned EXCEPTION_CONTINUE_EXECUTION in response to a noncontinuable exception.

Debugging-Related Exceptions

  • EXCEPTION_BREAKPOINT A breakpoint was encountered.
  • EXCEPTION_SINGLE_STEP A trace trap or other single-instruction mechanism signaled that one instruction has been executed.
  • EXCEPTION_INVALID_HANDLE A function was passed an invalid handle.

Integer-Related Exceptions

  • EXCEPTION_INT_DIVIDE_BY_ZERO The thread tried to divide an integer value by an integer divisor of 0.
  • EXCEPTION_INT_OVERFLOW The result of an integer operation caused a carry out of the most significant bit of the result.

Floating Point_Related Exceptions

  • EXCEPTION_FLT_DENORMAL_OPERAND One of the operands in a floating-point operation is denormal. A denormal value is one that is too small to represent a standard floating-point value.
  • EXCEPTION_FLT_DIVIDE_BY_ZERO The thread tried to divide a floating-point value by a floating-point divisor of 0.
  • EXCEPTION_FLT_INEXACT_RESULT The result of a floating-point operation can't be represented exactly as a decimal fraction.
  • EXCEPTION_FLT_INVALID_OPERATION Represents any floating-point exception not included in this list.
  • EXCEPTION_FLT_OVERFLOW The exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type.
  • EXCEPTION_FLT_STACK_CHECK The stack overflowed or underflowed as the result of a floating-point operation.
  • EXCEPTION_FLT_UNDERFLOW The exponent of a floating-point operation is less than the magnitude allowed by the type.

The GetExceptionCode intrinsic function can be called only in an exception filter (between the parentheses following _ _except) or inside an exception handler. The following code is legal:

 _ _try { y = 0; x = 4 / y; } _ _except ( ((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) || (GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO)) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { switch (GetExceptionCode()) { case EXCEPTION_ACCESS_VIOLATION: // Handle the access violation.           break; case EXCEPTION_INT_DIVIDE_BY_ZERO: // Handle the integer divide by 0.           break; } } 

However, you cannot call GetExceptionCode from inside an exception filter function. To help you catch such errors, the compiler will produce a compilation error if you try to compile the following code:

 _ _try { y = 0; x = 4 / y; } _ _except (CoffeeFilter()) { // Handle the exception.     } LONG CoffeeFilter (void) { // Compilation error: illegal call to GetExceptionCode. return((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH); } 

You can get the desired effect by rewriting the code this way:

 _ _try { y = 0; x = 4 / y; } _ _except (CoffeeFilter(GetExceptionCode())) { // Handle the exception.     } LONG CoffeeFilter (DWORD dwExceptionCode) { return((dwExceptionCode == EXCEPTION_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH); } 

Exception codes follow the rules for error codes as defined inside the WinError.h file. Each DWORD is divided as shown in Table 24-1.

Table 24-1. The composition of an error code

Bits 31-30 29 28 27-16 15-0
Contents Severity Microsoft/customer Reserved Facility code Exception code
Meaning 0=Success
1=Informational
2=Warning
3=Error
0=Microsoft-defined code
1=customer-defined code
Must be 0 Microsoft-defined (see table below) Microsoft/customer-defined

Currently, Microsoft defines the following facility codes.

Facility Code Value Facility Code Value
FACILITY_NULL 0 FACILITY_CONTROL 10
FACILITY_RPC 1 FACILITY_CERT 11
FACILITY_DISPATCH 2 FACILITY_INTERNET 12
FACILITY_STORAGE 3 FACILITY_MEDIASERVER 13
FACILITY_ITF 4 FACILITY_MSMQ 14
FACILITY_WIN32 7 FACILITY_SETUPAPI 15
FACILITY_WINDOWS 8 FACILITY_SCARD 16
FACILITY_SECURITY 9 FACILITY_COMPLUS 17

So here's what we get if we pick apart the EXCEPTION_ACCESS_VIOLATION exception code. Looking up EXCEPTION_ACCESS_VIOLATION in WinBase.h, we see that it has a value of 0xc0000005:

 C 0 0 0 0 0 0 5 (hexadecimal) 1100 0000 0000 0000 0000 0000 0000 0101 (binary) 

Bits 30 & 31 are both set to 1, indicating that an access violation is an error (the thread cannot continue running). Bit 29 is 0, meaning that Microsoft has defined this code. Bit 28 is 0 because it is reserved for future use. Bits 16 through 27 are 0, indicating FACILITY_NULL (an access violation can happen anywhere in the system; it is not an exception that only occurs when using certain facilities). Bits 0 through 15 contain the value 5, which just means that Microsoft defined an access violation as code 5.



Programming Applications for Microsoft Windows
Programming Applications for Microsoft Windows (Microsoft Programming Series)
ISBN: 1572319968
EAN: 2147483647
Year: 1999
Pages: 193

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net