Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
error.h
Go to the documentation of this file.00001 00004 /* 00005 * Copyright © 2000, 2001 Sofus Mortensen 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00018 00019 #ifndef COMET_ERROR_H 00020 #define COMET_ERROR_H 00021 00022 #include <comet/config.h> 00023 00024 #include <stdexcept> 00025 #include <string> 00026 00027 #include <comet/error_fwd.h> 00028 #include <comet/bstr.h> 00029 #include <comet/ptr.h> 00030 #include <comet/uuid_fwd.h> 00031 00032 #pragma warning(push) 00033 #pragma warning(disable : 4290) 00034 00035 namespace comet { 00036 00037 namespace impl { 00038 00039 inline com_ptr<IErrorInfo> GetErrorInfo() throw() 00040 { 00041 IErrorInfo* ei = 0; 00042 ::GetErrorInfo(0, &ei); 00043 return com_ptr<IErrorInfo>(auto_attach(ei)); 00044 } 00045 00046 inline com_ptr<ICreateErrorInfo> CreateErrorInfo() throw() 00047 { 00048 ICreateErrorInfo* cei = 0; 00049 ::CreateErrorInfo(&cei); 00050 return com_ptr<ICreateErrorInfo>(auto_attach(cei)); 00051 } 00052 00053 template<typename Itf> inline bool supports_ErrorInfo(Itf* p) 00054 { 00055 com_ptr<ISupportErrorInfo> q = com_cast(com_ptr<Itf>(p)); 00056 if (q == 0) return false; 00057 return S_OK == q->InterfaceSupportsErrorInfo(uuidof<Itf>()); 00058 } 00059 00060 } 00064 00067 template<typename Itf> inline void throw_com_error(Itf* p, HRESULT hr) 00068 { 00069 if (impl::supports_ErrorInfo(p)) 00070 { 00071 com_ptr<IErrorInfo> ei = impl::GetErrorInfo(); 00072 if (ei.is_null() == false) impl::throw_com_error_(hr, ei); 00073 } 00074 throw com_error(hr); 00075 } 00076 00080 class com_error : public std::runtime_error 00081 { 00082 public: 00084 00088 explicit com_error(HRESULT hr) : hr_(hr), std::runtime_error("") 00089 {} 00090 00092 00098 explicit com_error(const bstr_t& msg, HRESULT hr = E_FAIL) : hr_(hr), std::runtime_error("") 00099 { 00100 com_ptr<ICreateErrorInfo> cei(impl::CreateErrorInfo()); 00101 if ( !cei.is_null() ) { 00102 try { 00103 cei->SetDescription(msg.in()); 00104 ei_ = com_ptr<IErrorInfo>( com_cast(cei)) ; 00105 } catch (std::bad_alloc&) 00106 {} 00107 } 00108 } 00110 00118 explicit com_error(const bstr_t &msg, HRESULT hr, const bstr_t &src, const uuid_t &iid = uuid_t(), 00119 const bstr_t &helpFile=bstr_t(), DWORD helpContext = -1) 00120 : hr_(hr), std::runtime_error("") 00121 { 00122 com_ptr<ICreateErrorInfo> cei(impl::CreateErrorInfo()); 00123 if ( ! cei.is_null() ) 00124 { 00125 try { 00126 cei->SetDescription(msg.in()); 00127 if (!src.is_null() ) 00128 cei->SetSource( src.in() ); 00129 if (iid != uuid_t()) 00130 cei->SetGUID( iid ); 00131 if (!helpFile.is_null()) 00132 { 00133 cei->SetHelpFile( helpFile.in() ); 00134 cei->SetHelpContext( helpContext ); 00135 } 00136 ei_ = com_ptr<IErrorInfo>( com_cast(cei)) ; 00137 } catch (std::bad_alloc&) 00138 {} 00139 } 00140 } 00141 00143 explicit com_error(HRESULT hr, const com_ptr<IErrorInfo>& ei) : hr_(hr), ei_(ei), std::runtime_error("") 00144 {} 00145 00146 public: 00148 00155 const char* what() const throw() 00156 { 00157 try { 00158 if (what_.empty()) { 00159 what_ = s_str(); 00160 } 00161 } catch (std::bad_alloc&) { 00162 return 0; 00163 } 00164 00165 return what_.c_str(); 00166 } 00168 std::string s_str() const 00169 { 00170 std::string ret; 00171 get_str(ret); 00172 return ret; 00173 } 00175 std::wstring w_str() const 00176 { 00177 std::wstring ret; 00178 get_str(ret); 00179 return ret; 00180 } 00182 tstring t_str() const 00183 { 00184 tstring ret; 00185 get_str(ret); 00186 return ret; 00187 } 00188 00189 private: 00190 void get_str( std::string &ret) const throw() 00191 { 00192 if (ei_.is_null() == false) { 00193 bstr_t bs; 00194 if (SUCCEEDED(ei_->GetDescription(bs.out())) && !bs.is_empty()) { 00195 ret= bs.s_str(); 00196 return; 00197 } 00198 } 00199 LPVOID lpMsgBuf; 00200 if (FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 00201 NULL, hr_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 00202 (LPSTR) &lpMsgBuf, 0, NULL)) 00203 { 00204 ret = (const char*)lpMsgBuf; 00205 LocalFree(lpMsgBuf); 00206 } 00207 } 00208 void get_str( std::wstring &ret) const throw() 00209 { 00210 if (ei_.is_null() == false) { 00211 bstr_t bs; 00212 if (SUCCEEDED(ei_->GetDescription(bs.out())) && !bs.is_empty()) { 00213 ret = bs.w_str(); 00214 return; 00215 } 00216 } 00217 LPVOID lpMsgBuf; 00218 if (FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 00219 NULL, hr_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 00220 (LPWSTR) &lpMsgBuf, 0, NULL)) 00221 { 00222 ret = (const wchar_t*)lpMsgBuf; 00223 LocalFree(lpMsgBuf); 00224 } 00225 } 00226 public: 00227 00230 HRESULT hr() const throw() 00231 { 00232 return hr_; 00233 } 00234 00236 00237 00239 bstr_t description() const 00240 { 00241 bstr_t rv; 00242 if (!ei_.is_null()) ei_->GetDescription( rv.out() ) | raise_exception; 00243 return rv; 00244 } 00245 00247 bstr_t source() const 00248 { 00249 bstr_t rv; 00250 if (!ei_.is_null()) ei_->GetSource( rv.out() ) | raise_exception; 00251 return rv; 00252 } 00253 00255 GUID guid() const 00256 { 00257 GUID rv; 00258 if (!ei_.is_null()) ei_->GetGUID( &rv ) | raise_exception; 00259 else ZeroMemory(&rv, sizeof(rv)); 00260 return rv; 00261 } 00262 00264 bstr_t help_file() const 00265 { 00266 bstr_t rv; 00267 if (!ei_.is_null()) ei_->GetHelpFile( rv.out() ) | raise_exception; 00268 return rv; 00269 } 00270 00271 00273 DWORD help_context() const 00274 { 00275 DWORD rv = 0; 00276 if (!ei_.is_null()) ei_->GetHelpContext( &rv ) | raise_exception; 00277 return rv; 00278 } 00280 00282 com_ptr<IErrorInfo> get_ei() const 00283 { 00284 return ei_; 00285 } 00286 00287 private: 00288 mutable std::string what_; 00289 com_ptr<IErrorInfo> ei_; 00290 HRESULT hr_; 00291 }; 00292 00293 namespace impl { 00294 00295 inline HRESULT return_com_error(HRESULT hr, const bstr_t &desc, const bstr_t &src = auto_attach(BSTR(NULL)), 00296 const uuid_t &iid=CLSID_NULL, const bstr_t &helpFile=bstr_t(), DWORD helpContext = -1) 00297 { 00298 com_ptr<ICreateErrorInfo> cei(impl::CreateErrorInfo()); 00299 if (cei.is_null() == false) { 00300 try { 00301 cei->SetDescription(desc.in()); 00302 if (!src.is_null() ) 00303 cei->SetSource( src.in() ); 00304 if (iid != uuid_t()) 00305 cei->SetGUID( iid ); 00306 if (!helpFile.is_null()) 00307 { 00308 cei->SetHelpFile( helpFile.in() ); 00309 cei->SetHelpContext( helpContext ); 00310 } 00311 com_ptr<IErrorInfo> ei = com_cast(cei); 00312 ::SetErrorInfo(0, ei.in()); 00313 } catch (std::bad_alloc&) 00314 {} 00315 } 00316 return hr; 00317 } 00318 inline HRESULT return_com_error(const std::exception& err, const bstr_t &src = auto_attach(BSTR(NULL)), 00319 const uuid_t &iid=CLSID_NULL, const bstr_t &helpFile=bstr_t(), DWORD helpContext = -1) 00320 { 00321 return return_com_error( E_FAIL, bstr_t(err.what()),src,iid,helpFile, helpContext ); 00322 } 00323 inline HRESULT return_com_error(const com_error& err, const bstr_t &src = bstr_t(), const uuid_t &iid = CLSID_NULL) throw() 00324 { 00325 const bstr_t &cursrc =err.source(); 00326 const uuid_t &curiid =err.guid(); 00327 // Return error info with more info. 00328 return return_com_error( err.hr(), err.description(), cursrc.is_null()?src:cursrc, 00329 curiid.is_null()?iid:curiid, err.help_file(), err.help_context()); 00330 } 00331 00332 00333 inline void throw_com_error_(HRESULT hr, const com_ptr<IErrorInfo>& ei) 00334 { 00335 throw_error_handler<true>::throw_error(hr, ei); 00336 } 00337 00338 // Raising an HRESULT with a message 00339 inline void raise_exception_t::operator()(const bstr_t& msg, HRESULT hr/* = E_FAIL*/) const 00340 { 00341 throw com_error(msg, hr); 00342 } 00343 00344 // Raising an HRESULT 00345 inline void raise_exception_t::operator()(HRESULT hr) const 00346 { 00347 throw com_error(hr); 00348 } 00349 00350 } // namespace impl 00351 template<bool OVERRIDE> 00352 inline void throw_error_handler<OVERRIDE>::throw_error(HRESULT hr, const com_ptr<IErrorInfo> &ei) 00353 { 00354 throw com_error(hr, ei); 00355 } 00357 } 00358 00359 #pragma warning(pop) 00360 00361 #endif