Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
handle_except.h
Go to the documentation of this file.00001 00006 #ifndef COMET_HANDLE_EXCEPT_H 00007 #define COMET_HANDLE_EXCEPT_H 00008 00009 #ifdef _SHOW_INC 00010 #pragma message(" #Include " __FILE__) 00011 #endif 00012 00043 #ifdef COMET_DISABLE_EXCEPTION_RETHROW_CATCH 00044 #define COMET_CATCH_CLASS_EX(funcName,iid) \ 00045 catch ( const com_error &err) { \ 00046 return comet_exception_handler<true>::catcher_com_error(err, impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \ 00047 } catch ( const std::exception &err) { \ 00048 return comet_exception_handler<true>::catcher_exception(err, impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \ 00049 } catch ( HRESULT hr ) { \ 00050 return comet_exception_handler<true>::catcher_hr(hr, impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \ 00051 } catch (...) { \ 00052 return comet_exception_handler<true>::catcher_all( impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \ 00053 } 00054 00055 #define COMET_CATCH_UNKNOWN(funcName, iid, clsname) \ 00056 catch ( const com_error &err) { \ 00057 comet_exception_handler<true>::catcher_com_error(err, source_info_t(funcName, iid, clsname)); \ 00058 } catch ( const std::exception &err) { \ 00059 comet_exception_handler<true>::catcher_exception(err, source_info_t(funcName, iid, clsname)); \ 00060 } catch ( HRESULT hr ) { \ 00061 comet_exception_handler<true>::catcher_hr(hr, source_info_t(funcName, iid, clsname)); \ 00062 } catch (...) { \ 00063 comet_exception_handler<true>::catcher_all( source_info_t(funcName, iid, clsname)); \ 00064 } 00065 00066 00067 #else // COMET_DISABLE_EXCEPTION_RETHROW_CATCH 00068 00069 #define COMET_CATCH_CLASS_EX( funcName, iid) \ 00070 catch ( ... ) { \ 00071 return comet_exception_handler<true>::rethrow( impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \ 00072 } 00073 00074 #define COMET_CATCH_UNKNOWN(funcName, iid, clsname) \ 00075 catch ( ... ) { \ 00076 comet_exception_handler<true>::rethrow( source_info_t(funcName, iid, clsname)); \ 00077 } 00078 00079 #endif 00080 00085 #define COMET_CATCH_CLASS(funcName) COMET_CATCH_CLASS_EX(funcName, comtype<interface_is>::uuid()) 00086 00087 namespace comet { 00088 00092 00093 struct source_info_t 00094 { 00096 source_info_t() {} 00098 source_info_t(const bstr_t &par_function, const uuid_t &par_interface_uuid = uuid_t(), const bstr_t &par_coclass_name = bstr_t() ) 00099 : function_name(par_function), interface_uuid(par_interface_uuid), coclass_name(par_coclass_name) {} 00100 00101 bstr_t function_name; 00102 bstr_t coclass_name; 00103 uuid_t coclass_uuid; 00104 uuid_t interface_uuid; 00105 00106 bstr_t source_override; 00107 00111 bstr_t source() const 00112 { 00113 if ( !source_override.is_empty()) 00114 { 00115 return source_override; 00116 } 00117 if (coclass_name.is_empty()) 00118 { 00119 return function_name; 00120 } 00121 if (function_name.is_empty()) 00122 { 00123 return coclass_name; 00124 } 00125 return coclass_name + L"." + function_name; 00126 } 00127 00128 }; 00129 00130 namespace impl 00131 { 00137 template<bool> 00138 struct call_logger_redirect_ 00139 { 00140 template<bool> 00141 struct exe 00142 { 00143 static inline void log_exception(const tstring &type, const tstring &desc, const source_info_t &errorSource ,const source_info_t &callSource ) 00144 { } 00145 static inline bool can_log_exception() 00146 { return false; } 00147 }; 00148 }; 00149 } 00150 00155 template<bool OVERRIDE> 00156 struct error_logger_ 00157 { 00161 static inline bool can_log_exception() 00162 { 00163 return impl::call_logger_redirect_<OVERRIDE>::exe<OVERRIDE>::can_log_exception(); 00164 } 00165 00167 static inline void log_exception(const tstring &type, const tstring &desc, const source_info_t &errorSource ,const source_info_t &callSource ) 00168 { 00169 impl::call_logger_redirect_<OVERRIDE>::exe<OVERRIDE>::log_exception(type,desc,errorSource, callSource); 00170 } 00171 00172 }; 00173 00179 template< bool OVERRIDE> 00180 struct comet_exception_handler 00181 { 00182 #ifndef COMET_DISABLE_EXCEPTION_RETHROW_CATCH 00183 00187 static inline HRESULT rethrow(const source_info_t &info) 00188 { 00189 try { 00190 throw; 00191 } catch ( const com_error &err) 00192 { 00193 return catcher_com_error( err, info); 00194 } 00195 catch ( const std::exception &err) 00196 { 00197 return catcher_exception( err, info); 00198 } 00199 catch ( HRESULT hr ) 00200 { 00201 return catcher_hr( hr, info ); 00202 } 00203 catch (...) 00204 { 00205 return catcher_all(info); 00206 } 00207 00208 } 00209 #endif // COMET_DISABLE_EXCEPTION_RETHROW_CATCH 00210 00212 static inline HRESULT catcher_com_error( const com_error &err,const source_info_t &info) 00213 { 00214 if ( error_logger_<OVERRIDE>::can_log_exception() ) 00215 { 00216 source_info_t errorInfo; 00217 errorInfo.interface_uuid = err.guid(); 00218 errorInfo.source_override = err.source(); 00219 error_logger_<OVERRIDE>::log_exception( _T("comet::com_error"), err.t_str(), errorInfo, info); 00220 } 00221 return impl::return_com_error(err, info.source(), info.interface_uuid); 00222 } 00224 static inline HRESULT catcher_exception(const std::exception& err,const source_info_t &info) 00225 { 00226 if ( error_logger_<OVERRIDE>::can_log_exception() ) 00227 { 00228 error_logger_<OVERRIDE>::log_exception( _T("std::exception"), 00229 bstr_t(err.what()).t_str(), 00230 source_info_t(), info); 00231 } 00232 return impl::return_com_error(err, info.source(), info.interface_uuid); 00233 } 00235 static inline HRESULT catcher_hr( HRESULT hr,const source_info_t &info) 00236 { 00237 return impl::return_com_error(hr, bstr_t(), info.source(), info.interface_uuid); 00238 } 00240 static inline HRESULT catcher_all( const source_info_t &info) 00241 { 00242 COMET_NOTUSED(info); 00243 throw; 00244 } 00245 }; 00246 00247 00248 namespace impl 00249 { 00253 struct handle_exception_default_marker {}; 00254 00258 template <typename O> 00259 struct do_get_source_info_t 00260 { 00264 template <bool USETHIS> 00265 struct execute_handle 00266 { 00267 inline static void get_source_info(O * pThis, source_info_t &info) 00268 { 00269 pThis->get_source_info_( info ); 00270 } 00271 }; 00275 template <> 00276 struct execute_handle<false> 00277 { 00278 inline static void get_source_info(O *pThis, const source_info_t &info ) 00279 { 00280 COMET_NOTUSED(pThis); 00281 COMET_NOTUSED(info); 00282 // return impl::do_handle_exception<nil, IFACE>(src); 00283 } 00284 }; 00285 00289 inline static source_info_t exec( O *pThis, source_info_t info) 00290 { 00291 // Either call the coclass exception handler, or the project default. 00292 execute_handle<type_traits::conversion<O&, handle_exception_default_marker>::exists>::get_source_info( pThis, info); 00293 /* ERRORS: If the conversion is ambiguous here, then there are probably two ways of 00294 * getting to handle_exception_default_marker, usually via handle_exception_default<COCLASS>, 00295 * which is already provided by by IProvideClassInfoImpl<COCLASS>. 00296 */ 00297 return info; 00298 } 00299 }; 00300 } 00301 00307 template<typename COCLASS> 00308 struct handle_exception_default 00309 : impl::handle_exception_default_marker // Required to mark the class as being able to handle exceptions with coclass information 00310 { 00311 void get_source_info_( source_info_t &info) 00312 { 00313 info.coclass_name = COCLASS::name(); 00314 info.coclass_uuid = comtype<COCLASS>::uuid(); 00315 } 00316 }; 00317 // Handles the case where there is no coclass, and therefore no coclass name. 00318 template<> 00319 struct handle_exception_default<nil> : impl::handle_exception_default_marker 00320 { 00321 void get_source_info_( source_info_t &info) 00322 { 00323 COMET_NOTUSED(info); 00324 } 00325 }; 00327 } 00328 #endif /* COMET_HANDLE_EXCEPT_H */