| Index: chrome_frame/exception_barrier.h
|
| ===================================================================
|
| --- chrome_frame/exception_barrier.h (revision 45764)
|
| +++ chrome_frame/exception_barrier.h (working copy)
|
| @@ -1,96 +1,196 @@
|
| // Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
| -
|
| +//
|
| // A class to make it easy to tag exception propagation boundaries and
|
| // get crash reports of exceptions that pass over same.
|
| +//
|
| +// An exception barrier is used to report exceptions that pass through
|
| +// a boundary where exceptions shouldn't pass, such as e.g. COM interface
|
| +// boundaries.
|
| +// This is handy for any kind of plugin code, where if the exception passes
|
| +// through unhindered, it'll either be swallowed by an SEH exception handler
|
| +// above us on the stack, or be reported as an unhandled exception for
|
| +// the application hosting the plugin code.
|
| +//
|
| +// IMPORTANT NOTE: This class has crash_reporting disabled by default. To
|
| +// enable crash reporting call:
|
| +//
|
| +// @code
|
| +// ExceptionBarrierBase::set_crash_handling(true)
|
| +// @endcode
|
| +//
|
| +// somewhere in your initialization code.
|
| +//
|
| +// Then, to use this class, simply instantiate an ExceptionBarrier just inside
|
| +// the code boundary, like this:
|
| +// @code
|
| +// HRESULT SomeObject::SomeCOMMethod(...) {
|
| +// ExceptionBarrier report_crashes;
|
| +//
|
| +// ... other code here ...
|
| +// }
|
| +// @endcode
|
| +//
|
| +// There are three ExceptionBarrier types defined here:
|
| +// 1) ExceptionBarrier which reports all crashes it sees.
|
| +// 2) ExceptionBarrierReportOnlyModule which reports only crashes occurring
|
| +// in this module.
|
| +// 3) ExceptionBarrierCustomHandler which calls the handler set by a call
|
| +// to ExceptionBarrierCallCustomHandler::set_custom_handler(). Note that
|
| +// there is one custom handler for all ExceptionBarrierCallCustomHandler
|
| +// instances. If set_custom_handler() is never called, this places an
|
| +// SEH in the chain that just returns ExceptionContinueSearch.
|
| +
|
| #ifndef CHROME_FRAME_EXCEPTION_BARRIER_H_
|
| #define CHROME_FRAME_EXCEPTION_BARRIER_H_
|
|
|
| #include <windows.h>
|
|
|
| -/// This is the type dictated for an exception handler by the platform ABI
|
| -/// @see _except_handler in excpt.h
|
| -typedef EXCEPTION_DISPOSITION (__cdecl *ExceptionHandlerFunc)(
|
| - struct _EXCEPTION_RECORD *exception_record,
|
| - void * establisher_frame,
|
| - struct _CONTEXT *context,
|
| - void * reserved);
|
| +extern "C" IMAGE_DOS_HEADER __ImageBase;
|
|
|
| -/// The type of an exception record in the exception handler chain
|
| +// This is the type dictated for an exception handler by the platform ABI
|
| +// @see _except_handler in excpt.h
|
| +typedef EXCEPTION_DISPOSITION (__cdecl* ExceptionHandlerFunc)(
|
| + struct _EXCEPTION_RECORD* exception_record,
|
| + void* establisher_frame,
|
| + struct _CONTEXT* context,
|
| + void* reserved);
|
| +
|
| +// The type of an exception record in the exception handler chain
|
| struct EXCEPTION_REGISTRATION {
|
| - EXCEPTION_REGISTRATION *prev;
|
| + EXCEPTION_REGISTRATION* prev;
|
| ExceptionHandlerFunc handler;
|
| };
|
|
|
| -/// This is our raw exception handler, it must be declared extern "C" to
|
| -/// match up with the SAFESEH declaration in our corresponding ASM file
|
| +// This is our raw exception handler, it must be declared extern "C" to
|
| +// match up with the SAFESEH declaration in our corresponding ASM file.
|
| extern "C" EXCEPTION_DISPOSITION __cdecl
|
| -ExceptionBarrierHandler(struct _EXCEPTION_RECORD *exception_record,
|
| - void * establisher_frame,
|
| - struct _CONTEXT *context,
|
| - void * reserved);
|
| +ExceptionBarrierHandler(struct _EXCEPTION_RECORD* exception_record,
|
| + void* establisher_frame,
|
| + struct _CONTEXT* context,
|
| + void* reserved);
|
|
|
| -/// An exception barrier is used to report exceptions that pass through
|
| -/// a boundary where exceptions shouldn't pass, such as e.g. COM interface
|
| -/// boundaries.
|
| -/// This is handy for any kind of plugin code, where if the exception passes
|
| -/// through unhindered, it'll either be swallowed by an SEH exception handler
|
| -/// above us on the stack, or be reported as an unhandled exception for
|
| -/// the application hosting the plugin code.
|
| -///
|
| -/// To use this class, simply instantiate an ExceptionBarrier just inside
|
| -/// the code boundary, like this:
|
| -/// @code
|
| -/// HRESULT SomeObject::SomeCOMMethod(...) {
|
| -/// ExceptionBarrier report_crashes;
|
| -///
|
| -/// ... other code here ...
|
| -/// }
|
| -/// @endcode
|
| -class ExceptionBarrier {
|
| +// An alternate raw exception handler that reports crashes only for the current
|
| +// module. It must be declared extern "C" to match up with the SAFESEH
|
| +// declaration in our corresponding ASM file.
|
| +extern "C" EXCEPTION_DISPOSITION __cdecl
|
| +ExceptionBarrierReportOnlyModuleHandler(
|
| + struct _EXCEPTION_RECORD* exception_record,
|
| + void* establisher_frame,
|
| + struct _CONTEXT* context,
|
| + void* reserved);
|
| +
|
| +// An alternate raw exception handler that calls out to a custom handler.
|
| +// It must be declared extern "C" to match up with the SAFESEH declaration in
|
| +// our corresponding ASM file.
|
| +extern "C" EXCEPTION_DISPOSITION __cdecl
|
| +ExceptionBarrierCallCustomHandler(
|
| + struct _EXCEPTION_RECORD* exception_record,
|
| + void* establisher_frame,
|
| + struct _CONTEXT* context,
|
| + void* reserved);
|
| +
|
| +
|
| +// @name These are implemented in the associated .asm file
|
| +// @{
|
| +extern "C" void WINAPI RegisterExceptionRecord(
|
| + EXCEPTION_REGISTRATION* registration,
|
| + ExceptionHandlerFunc func);
|
| +extern "C" void WINAPI UnregisterExceptionRecord(
|
| + EXCEPTION_REGISTRATION* registration);
|
| +// @}
|
| +
|
| +
|
| +// Traits classes for ExceptionBarrierT.
|
| +class EBTraitsBase {
|
| public:
|
| - /// Register the barrier in the SEH chain
|
| - ExceptionBarrier();
|
| + static void UnregisterException(EXCEPTION_REGISTRATION* registration) {
|
| + UnregisterExceptionRecord(registration);
|
| + }
|
| +};
|
|
|
| - /// And unregister on destruction
|
| - ~ExceptionBarrier();
|
| +class EBReportAllTraits : public EBTraitsBase {
|
| + public:
|
| + static void RegisterException(EXCEPTION_REGISTRATION* registration) {
|
| + RegisterExceptionRecord(registration, ExceptionBarrierHandler);
|
| + }
|
| +};
|
|
|
| - /// Signature of the handler function which gets notified when
|
| - /// an exception propagates through a barrier.
|
| - typedef void (CALLBACK *ExceptionHandler)(EXCEPTION_POINTERS *ptrs);
|
| +class EBReportOnlyThisModuleTraits : public EBTraitsBase {
|
| + public:
|
| + static void RegisterException(EXCEPTION_REGISTRATION* registration) {
|
| + RegisterExceptionRecord(registration,
|
| + ExceptionBarrierReportOnlyModuleHandler);
|
| + }
|
| +};
|
|
|
| - /// @name Accessors
|
| - /// @{
|
| - static void set_handler(ExceptionHandler handler) { s_handler_ = handler; }
|
| - static ExceptionHandler handler() { return s_handler_; }
|
| - /// @}
|
| +class EBCustomHandlerTraits : public EBTraitsBase {
|
| + public:
|
| + static void RegisterException(EXCEPTION_REGISTRATION* registration) {
|
| + RegisterExceptionRecord(registration,
|
| + ExceptionBarrierCallCustomHandler);
|
| + }
|
| +};
|
|
|
| - private:
|
| - /// Our SEH frame
|
| - EXCEPTION_REGISTRATION registration_;
|
| +class ExceptionBarrierConfig {
|
| + public:
|
| + // Used to globally enable or disable crash handling by ExceptionBarrierBase
|
| + // instances.
|
| + static void set_enabled(bool enabled) {
|
| + s_enabled_ = enabled;
|
| + }
|
| + static bool enabled() { return s_enabled_; }
|
|
|
| - /// The function that gets invoked if an exception
|
| - /// propagates through a barrier
|
| - static ExceptionHandler s_handler_;
|
| + // Whether crash reports are enabled.
|
| + static bool s_enabled_;
|
| };
|
|
|
| -/// @name These are implemented in the associated .asm file
|
| -/// @{
|
| -extern "C" void WINAPI RegisterExceptionRecord(
|
| - EXCEPTION_REGISTRATION *registration,
|
| - ExceptionHandlerFunc func);
|
| -extern "C" void WINAPI UnregisterExceptionRecord(
|
| - EXCEPTION_REGISTRATION *registration);
|
| -/// @}
|
| +template <typename RegistrarTraits>
|
| +class ExceptionBarrierT {
|
| + public:
|
| + // Register the barrier in the SEH chain
|
| + ExceptionBarrierT() {
|
| + RegistrarTraits::RegisterException(®istration_);
|
| + }
|
|
|
| + // Unregister on destruction
|
| + virtual ~ExceptionBarrierT() {
|
| + RegistrarTraits::UnregisterException(®istration_);
|
| + }
|
|
|
| -inline ExceptionBarrier::ExceptionBarrier() {
|
| - RegisterExceptionRecord(®istration_, ExceptionBarrierHandler);
|
| -}
|
| + protected:
|
| + // Our SEH frame
|
| + EXCEPTION_REGISTRATION registration_;
|
| +};
|
|
|
| -inline ExceptionBarrier::~ExceptionBarrier() {
|
| - UnregisterExceptionRecord(®istration_);
|
| -}
|
| +// This class allows for setting a custom exception handler function. The
|
| +// handler is shared among all instances. This class is intended to enable
|
| +// testing of the SEH registration.
|
| +template <typename RegistrarTraits>
|
| +class ExceptionBarrierCustomHandlerT :
|
| + public ExceptionBarrierT<typename RegistrarTraits> {
|
| + public:
|
| + // Signature of the handler function which gets notified when
|
| + // an exception propagates through a barrier.
|
| + typedef void (CALLBACK* CustomExceptionHandler)(EXCEPTION_POINTERS* ptrs);
|
|
|
| + // Used to set a global custom handler used by all
|
| + // ExceptionBarrierCustomHandler instances.
|
| + static void set_custom_handler(CustomExceptionHandler handler) {
|
| + s_custom_handler_ = handler;
|
| + }
|
| + static CustomExceptionHandler custom_handler() { return s_custom_handler_; }
|
| +
|
| + private:
|
| + static CustomExceptionHandler s_custom_handler_;
|
| +};
|
| +
|
| +// Convenience typedefs for the ExceptionBarrierT specializations.
|
| +typedef ExceptionBarrierT<EBReportAllTraits> ExceptionBarrier;
|
| +typedef ExceptionBarrierT<EBReportOnlyThisModuleTraits>
|
| + ExceptionBarrierReportOnlyModule;
|
| +typedef ExceptionBarrierCustomHandlerT<EBCustomHandlerTraits>
|
| + ExceptionBarrierCustomHandler;
|
| +
|
| #endif // CHROME_FRAME_EXCEPTION_BARRIER_H_
|
|
|