Compartir a través de


Usar un controlador de excepciones vectoriales

En el código de ejemplo siguiente se muestra cómo usar el control de excepciones vectoriales. Usa la función AddVectoredExceptionHandler para agregar varios controladores, probar los controladores y, a continuación, usa la función RemoveVectoredExceptionHandler para quitar los controladores.

Windows de 64 bits: Este código no es adecuado para Windows de 64 bits.

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

// NOTE: The CONTEXT structure contains processor-specific 
// information. This sample was designed for X86 processors.

//addVectoredExceptionHandler constants:
//CALL_FIRST means call this exception handler first;
//CALL_LAST means call this exception handler last
#define CALL_FIRST 1  
#define CALL_LAST 0

LONG Sequence=1;
LONG Actual[3];

LONG WINAPI
VectoredHandler1(
    struct _EXCEPTION_POINTERS *ExceptionInfo
    )
{
    UNREFERENCED_PARAMETER(ExceptionInfo);
    
    Actual[0] = Sequence++;
    return EXCEPTION_CONTINUE_SEARCH;
}

LONG WINAPI
VectoredHandler2(
    struct _EXCEPTION_POINTERS *ExceptionInfo
    )
{
    UNREFERENCED_PARAMETER(ExceptionInfo);

    Actual[1] = Sequence++;
    return EXCEPTION_CONTINUE_SEARCH;
}

LONG WINAPI
VectoredHandler3(
    struct _EXCEPTION_POINTERS *ExceptionInfo
    )
{
    UNREFERENCED_PARAMETER(ExceptionInfo);

    Actual[2] = Sequence++;
    return EXCEPTION_CONTINUE_SEARCH;
}

LONG WINAPI
VectoredHandlerSkip1(
    struct _EXCEPTION_POINTERS *ExceptionInfo
    )
{
    PCONTEXT Context;
    
    Sequence++;
    Context = ExceptionInfo->ContextRecord;
    Actual[0] = 0xcc;
#ifdef _AMD64_
    Context->Rip++;
#else
    Context->Eip++;
#endif    
    return EXCEPTION_CONTINUE_EXECUTION;
}

LONG WINAPI
VectoredHandlerSkip2(
    struct _EXCEPTION_POINTERS *ExceptionInfo
    )
{
    PCONTEXT Context;
    
    Sequence++;
    Context = ExceptionInfo->ContextRecord;
    Actual[1] = 0xcc;
#ifdef _AMD64_
    Context->Rip++;
#else
    Context->Eip++;
#endif    
    return EXCEPTION_CONTINUE_EXECUTION;
}

LONG WINAPI
VectoredHandlerSkip3(
    struct _EXCEPTION_POINTERS *ExceptionInfo
    )
{
    PCONTEXT Context;
    
    Sequence++;
    Context = ExceptionInfo->ContextRecord;
    Actual[2] = 0xcc;
#ifdef _AMD64_
    Context->Rip++;
#else
    Context->Eip++;
#endif    
    return EXCEPTION_CONTINUE_EXECUTION;
}

BOOL CheckTest(
    char *Variation,
    PLONG e,
    PLONG a
    )
{
    int i;
    BOOL Pass = TRUE;

    for(i=0;i<3;i++) 
    {
        if (e[i] != a[i]) 
        {
            if (Variation) 
            {
                printf("%s Failed at %d Expected %d vs Actual %d\n", 
                        Variation, i, e[i], a[i]);
            }
            Pass = FALSE;
        }

        // Clear actual for next pass.
        a[i] = 0;
    }

    // Get ready for next pass.
    Sequence = 1;

    if (Variation) 
    {
        printf("Variation %s %s\n", Variation, 
                Pass ? "Passed" : "Failed");
    }
    return Pass;
}

void
CheckAllClear()
{
    LONG e[3];
    BOOL b = 0;

    e[0]=0;e[1]=0;e[2]=0;
    __try 
    {
        RaiseException(1,0,0,NULL);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        b = CheckTest(NULL,e,Actual);
    }
    if (!b) 
    {
        printf("Fatal error, handlers still registered.\n");
    }
}

void IllegalInst()
{
    char *ptr = 0;
    *ptr = 0;
}

void Test1()
{
    
    PVOID h1,h2,h3;
    LONG e[3];
     
    e[0]=1;e[1]=2;e[2]=3;
    h2 = AddVectoredExceptionHandler(CALL_FIRST,VectoredHandler2);
    h3 = AddVectoredExceptionHandler(CALL_LAST,VectoredHandler3);
    h1 = AddVectoredExceptionHandler(CALL_FIRST,VectoredHandler1);

    __try 
    {
        RaiseException(1,0,0,NULL);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        CheckTest("Test1a",e,Actual);
    }

    RemoveVectoredExceptionHandler(h1);
    RemoveVectoredExceptionHandler(h3);
    RemoveVectoredExceptionHandler(h2);
    CheckAllClear();
}

void Test2()
{
    
    PVOID h1,h2,h3;
    LONG e[3];
     
    e[0]=0xcc;e[1]=0;e[2]=0;
    h1 = AddVectoredExceptionHandler(1,VectoredHandlerSkip1);
    IllegalInst();
    CheckTest("Test2a",e,Actual);
    RemoveVectoredExceptionHandler(h1);
    CheckAllClear();

    e[0]=1;e[1]=2;e[2]=0xcc;
    h2 = AddVectoredExceptionHandler(CALL_FIRST,VectoredHandler2);
    h3 = AddVectoredExceptionHandler(CALL_LAST,VectoredHandlerSkip3);
    h1 = AddVectoredExceptionHandler(CALL_FIRST,VectoredHandler1);
    IllegalInst();
    CheckTest("Test2b",e,Actual);
    RemoveVectoredExceptionHandler(h1);
    RemoveVectoredExceptionHandler(h2);
    RemoveVectoredExceptionHandler(h3);
    CheckAllClear();

    e[0]=1;e[1]=0xcc;e[2]=0;
    h1 = AddVectoredExceptionHandler(CALL_LAST,VectoredHandler1);
    h2 = AddVectoredExceptionHandler(CALL_LAST,VectoredHandlerSkip2);
    h3 = AddVectoredExceptionHandler(CALL_LAST,VectoredHandler3);
    IllegalInst();
    CheckTest("Test2c",e,Actual);
    RemoveVectoredExceptionHandler(h1);
    RemoveVectoredExceptionHandler(h2);
    RemoveVectoredExceptionHandler(h3);
    CheckAllClear();

    e[0]=2;e[1]=0xcc;e[2]=1;
    h1 = AddVectoredExceptionHandler(CALL_LAST,VectoredHandler1);
    h3 = AddVectoredExceptionHandler(CALL_FIRST,VectoredHandler3);
    h2 = AddVectoredExceptionHandler(CALL_LAST,VectoredHandlerSkip2);
    __try 
    {
        IllegalInst();
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        // Should not make it to here.
        e[0]=0;e[1]=0;e[2]=0;
        CheckTest("Test2d-1",e,Actual);
    }
    CheckTest("Test2d-2",e,Actual);
    RemoveVectoredExceptionHandler(h1);
    RemoveVectoredExceptionHandler(h2);
    RemoveVectoredExceptionHandler(h3);
    CheckAllClear();
}

void main( )
{
    Test1();
    Test2();
}