views:

283

answers:

6

To test this problem I have written a minimal windows application. If I force an access violation in the WM_PAINT handler this exception never gets to the debugger. If started without debugger the access violation also does not show up. Usually you should get the Windows Error Reporting dialog.

Digging a bit deeper it seems that something in user32.dll catches all incoming exceptions. Is this normal behavior? Can I control this somehow? Isn't catching all exceptions a security risk? At least it is annoying as hell.

This is with a 32- and 64-bit application on Vista 64. On XP the exception seems to be handled as expected. Other windows messages have the same problem. Maybe all of them?

The WM_PAINT handler:

case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    *(int*)0 = 0;
    EndPaint(hWnd, &ps);
    break;
A: 

Exception will be thrown in WinXP and in Vista. I've just tested this in Vista in Debug and Release configurations. Do you have the same issue in new Win32 Application project?

Kirill V. Lyadvinsky
+1  A: 

DispatchMessage seems to now contain a SEH try catch block that inhibits exceptions generated by window procs.

You can still catch these exceptions in the debugger - depending on your visual studio version you need to open the debug->exceptions dialog and tick the "Break when an exception is thrown" column for all Win32 exceptions, or at least exception 0xc0000005

Chris Becke
I know but this is only a solution if using a debugger. And what is with all the other exceptions that might get thrown while handling windows messages? Do you have any official (or unofficial) documentation or reasoning for this change?
Sebastian Tusk
A: 

I've noticed that, when you have Aero enabled (which is by default in Vista), resizing windows tends to create many, many page faults. These aren't normal virtual memory-needs-to-be-paged-in faults, either. I suspect (though it's just a theory), that Aero redirects the graphics output to a protected chunk of memory, and catches the faults in order to know which bits of the visible surface need to be recomposited on the desktop. Perhaps that is eating other access violations as well.

Adrian McCarthy
Beginning with Vista video memory is virtualized. This shouldn't be correlated to any exceptions in applications. At least Aero enabled or not doesn't change anything with exception handling in windows messages.
Sebastian Tusk
You're right. The exception is dropped regardless of whether desktop compositing is enabled or not.
Adrian McCarthy
+1  A: 

As a workaround I remove all registered exception handlers in my window procedure. Quite ugly.

LRESULT CALLBACK window_proc( 
    HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    // get thread information block
    NT_TIB* tib;
    __asm {
        mov EAX, FS:[18h]
        mov [tib], EAX
    }
    // old exception handler list
    _EXCEPTION_REGISTRATION_RECORD* old_exception_handler = tib->ExceptionList;
    // remove all exception handler with exception of the default handler
    while( tib->ExceptionList->Next != (_EXCEPTION_REGISTRATION_RECORD*)-1 ) {
        tib->ExceptionList = tib->ExceptionList->Next;
    }

    LRESULT result = DefWindowProc( hwnd, uMsg, wParam, lParam );

    // restore old exception handler
    tib->ExceptionList = old_exception_handler;

    return result;
}
Sebastian Tusk
A: 

Starting from XP, the Vector Exception Handling functionality can be used. It has priority over all other kinds of exceptions. In my example, it correctly caught the Access Violation in the WM_PAINT message. Unfortunately, it also catches all other kinds of exceptions, which I should probably solve by checking for the exception code.

Patrick
+1  A: 

It's a known defect. Check the hotfix. http://support.microsoft.com/kb/976038

mljack