Search code examples
c++try-catchseh

Nested __try...__except clauses, how does this work?


I'm dealing with a function and a subfunction, the subfunction being called within the function. Both have a __try .. __except-clause, and I'd like to see the general exception handling in case of the function, and the specific one in case of the subfunction, in other words:

int function(){
__try{
  do_something();
  return subfunction();
  } __except (Exception_Execute_Handler_Something()){
  show("general exception");
  }

int subfunction(){
  __try{
    return do_something_else();
  } __except (Exception_Execute_Handler_Something_Else()){
    show("specific case");
  }

In this case:
When do_something() goes wrong, I see "general exception".
When do_something_else() goes wrong, I also see "general exception", which is not what I want.

What I want is:
When do_something() goes wrong, I want to see "general exception.
When do_something_else() goes wrong, I want to see "specific case".

Edit after Ben Voight's remark

There indeed is an exception filter, and this is currently checking the exception code for deciding whether or not to continue, as you can see here:

if (Exception->ExceptionCode == STATUS_ACCESS_VIOLATION)
  return EXCEPTION_CONTINUE_SEARCH;

I have, however, no knowledge at all in the structure and/or content of ExceptionRecord and ContextRecord, the two input parameters of the exception handling. Hereby I give an example of what those parameters look like in my particular case:

Exception record:

-   ExceptionRecord 0x0eecdec8 {ExceptionCode=3221225620 ExceptionFlags=0 ExceptionRecord=0x00000000 <NULL> ...}    _EXCEPTION_RECORD *
    ExceptionCode   3221225620  unsigned long // I guess this means division by zero
    ExceptionFlags  0   unsigned long
+   ExceptionRecord 0x00000000 <NULL>   _EXCEPTION_RECORD *
    ExceptionAddress    0x002c1993 {<Application>.exe!CClass::Main_Method(CInputClass & params), Line 46}   void *
    NumberParameters    0   unsigned long
+   ExceptionInformation    0x0eecdedc {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}    unsigned long[15]

ContextRecord:

-   ContextRecord   0x0eecdf18 {ContextFlags=65543 Dr0=0 Dr1=0 ...} _CONTEXT *
    ContextFlags    65543   unsigned long
    Dr0 0   unsigned long
    Dr1 0   unsigned long
    Dr2 0   unsigned long
    Dr3 0   unsigned long
    Dr6 0   unsigned long
    Dr7 0   unsigned long
-   FloatSave   {ControlWord=0 StatusWord=0 TagWord=0 ...}  _FLOATING_SAVE_AREA
    ControlWord 0   unsigned long
    StatusWord  0   unsigned long
    TagWord 0   unsigned long
    ErrorOffset 0   unsigned long
    ErrorSelector   0   unsigned long
    DataOffset  0   unsigned long
    DataSelector    0   unsigned long
+   RegisterArea    0x0eecdf50 ""   unsigned char[80] // all are zero
    Spare0  0   unsigned long
    SegGs   43  unsigned long
    SegFs   83  unsigned long
    SegEs   43  unsigned long
    SegDs   43  unsigned long
    Edi 80923496    unsigned long
    Esi 250405956   unsigned long
    Ebx 0   unsigned long
    Edx 0   unsigned long
    Ecx 0   unsigned long
    Eax 1   unsigned long
    Ebp 250405884   unsigned long
    Eip 2890131 unsigned long
    SegCs   35  unsigned long
    EFlags  66118   unsigned long
    Esp 250405880   unsigned long
    SegSs   43  unsigned long
+   ExtendedRegisters   0x0eecdfe4 "\x2 \x1"    unsigned char[512] // at first sight, not readable

Now my question has turned into:

In case I'm already inside another __try..__except clause, I'd return EXCEPTION_CONTINUE_SEARCH.

Does anybody know which of the mentioned ExceptionRecord or ContextRecord properties I can use for determining whether or not I am already inside another __try..__except clause?

New edit after again some more information

I've just found EXCEPTION_DISPOSITION, present in C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\include\excpt.h. This contains the function _except_handler(), which returns an EXCEPTION_DISPOSITION enum, which can be ExceptionNestedException (I believe this is the one I'm looking for).
So now the question turns into:

What parameters do I need to fill in in the function _except_handler() in order to know if I'm dealing with a nested exception (or does somebody know an easier way to get this done)?


Solution

  • Your code as written does not compile. Instead of:

    __except { ... }
    

    you need:

    __except (EXCEPTION_EXECUTE_HANDLER) { ... }
    

    Then it works as desired.

    Live demo