Changeset 2672 in vbox
- Timestamp:
- May 16, 2007 3:31:49 PM (17 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
-
include/VBox/com/ErrorInfo.h (modified) (9 diffs)
-
include/VBox/com/com.h (modified) (1 diff)
-
src/VBox/Main/ConsoleImpl.cpp (modified) (7 diffs)
-
src/VBox/Main/MachineImpl.cpp (modified) (7 diffs)
-
src/VBox/Main/VirtualBoxBase.cpp (modified) (3 diffs)
-
src/VBox/Main/VirtualBoxErrorInfoImpl.cpp (modified) (4 diffs)
-
src/VBox/Main/glue/ErrorInfo.cpp (modified) (9 diffs)
-
src/VBox/Main/glue/com.cpp (modified) (6 diffs)
-
src/VBox/Main/idl/VirtualBox.xidl (modified) (1 diff)
-
src/VBox/Main/include/VirtualBoxBase.h (modified) (8 diffs)
-
src/VBox/Main/include/VirtualBoxErrorInfoImpl.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/ErrorInfo.h
r1 r2672 28 28 #include "VBox/com/Guid.h" 29 29 #include "VBox/com/assert.h" 30 31 #include <iprt/memory> // for auto_copy_ptr 30 32 31 33 struct IProgress; … … 102 104 * pointer available. 103 105 */ 104 explicit ErrorInfo() : 105 mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) 106 { init(); } 106 explicit ErrorInfo() 107 : mIsBasicAvailable (false), mIsFullAvailable (false) 108 , mResultCode (S_OK) 109 { init(); } 107 110 108 111 /** … … 118 121 * error 119 122 */ 120 template <class I> ErrorInfo (I *aPtr) : 121 mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) 122 { init (aPtr, COM_IIDOF(I)); } 123 template <class I> ErrorInfo (I *aPtr) 124 : mIsBasicAvailable (false), mIsFullAvailable (false) 125 , mResultCode (S_OK) 126 { init (aPtr, COM_IIDOF(I)); } 123 127 124 128 /** … … 129 133 * an error 130 134 */ 131 template <class I> ErrorInfo (const ComPtr <I> &aPtr) : 132 mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) 133 { init (static_cast <I*> (aPtr), COM_IIDOF(I)); } 135 template <class I> ErrorInfo (const ComPtr <I> &aPtr) 136 : mIsBasicAvailable (false), mIsFullAvailable (false) 137 , mResultCode (S_OK) 138 { init (static_cast <I*> (aPtr), COM_IIDOF(I)); } 134 139 135 140 /** Specialization for the IVirtualBoxErrorInfo smart pointer */ 136 ErrorInfo (const ComPtr <IVirtualBoxErrorInfo> &aPtr) : 137 mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) 138 { init (aPtr); } 141 ErrorInfo (const ComPtr <IVirtualBoxErrorInfo> &aPtr) 142 : mIsBasicAvailable (false), mIsFullAvailable (false) 143 , mResultCode (S_OK) 144 { init (aPtr); } 139 145 140 146 /** … … 146 152 * holds error info to be fetched by this instance 147 153 */ 148 ErrorInfo (IVirtualBoxErrorInfo *aInfo) : 149 mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) 150 { init (aInfo); } 151 152 ~ErrorInfo(); 154 ErrorInfo (IVirtualBoxErrorInfo *aInfo) 155 : mIsBasicAvailable (false), mIsFullAvailable (false) 156 , mResultCode (S_OK) 157 { init (aInfo); } 158 159 virtual ~ErrorInfo(); 153 160 154 161 /** … … 201 208 202 209 /** 210 * Returns the next error information object or @c NULL if there is none. 211 */ 212 const ErrorInfo *getNext() const { return mNext.get(); } 213 214 /** 203 215 * Returns the name of the interface that defined the error 204 216 */ … … 233 245 protected: 234 246 235 ErrorInfo (bool dummy) : 236 mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) 237 {} 238 239 void init(); 240 void init (IUnknown *i, const GUID &iid); 241 void init (IVirtualBoxErrorInfo *info); 242 243 private: 244 245 bool mIsBasicAvailable; 246 bool mIsFullAvailable; 247 ErrorInfo (bool aDummy) 248 : mIsBasicAvailable (false), mIsFullAvailable (false) 249 , mResultCode (S_OK) 250 {} 251 252 void init (bool aKeepObj = false); 253 void init (IUnknown *aUnk, const GUID &aIID, bool aKeepObj = false); 254 void init (IVirtualBoxErrorInfo *aInfo); 255 256 bool mIsBasicAvailable : 1; 257 bool mIsFullAvailable : 1; 247 258 248 259 HRESULT mResultCode; … … 251 262 Bstr mText; 252 263 264 cppx::auto_copy_ptr <ErrorInfo> mNext; 265 253 266 Bstr mInterfaceName; 254 267 Guid mCalleeIID; 255 268 Bstr mCalleeName; 269 270 ComPtr <IUnknown> mErrorInfo; 256 271 }; 257 272 258 273 /** 259 * A convenience subclass of ErrorInfo ,that, given an IProgress interface274 * A convenience subclass of ErrorInfo that, given an IProgress interface 260 275 * pointer, reads its errorInfo attribute and uses the returned 261 276 * IVirtualBoxErrorInfo instance to construct itself. … … 277 292 }; 278 293 294 /** 295 * A convenience subclass of ErrorInfo that allows to preserve the current 296 * error info. Instances of this class fetch an error info object set on the 297 * current thread and keep a reference to it, which allows to restore it 298 * later using the #restore() method. This is useful to preserve error 299 * information returned by some method for the duration of making another COM 300 * call that may set its own error info and overwrite the existing 301 * one. Preserving and restoring error information makes sense when some 302 * method wants to return error information set by other call as its own 303 * error information while it still needs to make another call before return. 304 * 305 * The usage pattern is: 306 * <code> 307 * rc = foo->method(); 308 * if (FAILED (rc)) 309 * { 310 * ErrorInfoKeeper eik; 311 * ... 312 * // bar may return error info as well 313 * bar->method(); 314 * ... 315 * // restore error info from foo to return it to the caller 316 * eik.restore(); 317 * return rc; 318 * } 319 * </code> 320 */ 321 class ErrorInfoKeeper : public ErrorInfo 322 { 323 public: 324 325 /** Constructs a new instance that will fetch the current error info. */ 326 ErrorInfoKeeper() : ErrorInfo (false), mForgot (false) 327 { init (true /* aKeepObj */); } 328 329 /** 330 * Destroys this instance and automatically calls #restore() which will 331 * either restorr error info fetched by the constructor or do nothing 332 * if #forget() was called before destruction. */ 333 ~ErrorInfoKeeper() { if (!mForgot) restore(); } 334 335 /** 336 * Restores error info fetched by the constructor and forgets it 337 * afterwards. 338 * 339 * @return COM result of the restore operation. 340 */ 341 HRESULT restore(); 342 343 /** 344 * Forgets error info fetched by the constructor which prevents it from 345 * being restored by #restore() or by the destructor. 346 */ 347 void forget() { mForgot = 0; } 348 349 private: 350 351 bool mForgot : 1; 352 }; 353 279 354 }; // namespace com 280 355 -
trunk/include/VBox/com/com.h
r1 r2672 38 38 39 39 /** 40 * Shut downsthe COM runtime.40 * Shuts down the COM runtime. 41 41 * Must be called on every thread before termination. 42 * No anyCOM calls may be made after this method returns.42 * No COM calls may be made after this method returns. 43 43 */ 44 44 void Shutdown(); 45 46 /** 47 * Resolves a given interface ID to a string containing the interface name. 48 * If, for some reason, the given IID cannot be resolved to a name, a NULL 49 * string is returned. A non-NULL string returned by this funciton must be 50 * freed using SysFreeString(). 51 * 52 * @param aIID ID of the interface to get a name for 53 * @param aName Resolved interface name or @c NULL on error 54 */ 55 void GetInterfaceNameByIID (const GUID &aIID, BSTR *aName); 45 56 46 57 }; // namespace com -
trunk/src/VBox/Main/ConsoleImpl.cpp
r2651 r2672 1785 1785 if (FAILED (rc) && !taskCreationFailed) 1786 1786 { 1787 /* fetch anyexisting error info */1788 ErrorInfo ei;1787 /* preserve existing error info */ 1788 ErrorInfoKeeper eik; 1789 1789 1790 1790 if (beganSavingState) … … 1807 1807 else 1808 1808 setMachineStateLocally (lastMachineState); 1809 1810 /* restore fetched error info */1811 setError (ei);1812 1809 } 1813 1810 … … 2340 2337 if (FAILED (rc) && !taskCreationFailed) 2341 2338 { 2342 /* fetch anyexisting error info */2343 ErrorInfo ei;2339 /* preserve existing error info */ 2340 ErrorInfoKeeper eik; 2344 2341 2345 2342 if (beganTakingSnapshot && takingSnapshotOnline) … … 2363 2360 else 2364 2361 setMachineStateLocally (lastMachineState); 2365 2366 /* restore fetched error info */2367 setError (ei);2368 2362 } 2369 2363 … … 6795 6789 if (FAILED (hrc) || VBOX_FAILURE (vrc)) 6796 6790 { 6797 /* preserve the currenterror info */6798 ErrorInfo ei;6791 /* preserve existing error info */ 6792 ErrorInfoKeeper eik; 6799 6793 6800 6794 /* … … 6804 6798 HRESULT hrc2 = console->powerDown(); 6805 6799 AssertComRC (hrc2); 6806 6807 setError (ei);6808 6800 } 6809 6801 } … … 6860 6852 */ 6861 6853 6862 /* preserve the currenterror info */6863 ErrorInfo ei;6854 /* preserve existing error info */ 6855 ErrorInfoKeeper eik; 6864 6856 6865 6857 Assert (console->mpVM == NULL); 6866 6858 vmstateChangeCallback (NULL, VMSTATE_TERMINATED, VMSTATE_CREATING, 6867 6859 console); 6868 setError (ei);6869 6860 } 6870 6861 -
trunk/src/VBox/Main/MachineImpl.cpp
r2656 r2672 8951 8951 } 8952 8952 8953 /* fetch the currenterror info */8954 ErrorInfo mergeEi;8953 /* preserve existing error info */ 8954 ErrorInfoKeeper mergeEik; 8955 8955 HRESULT mergeRc = rc; 8956 8956 … … 9026 9026 while (0); 9027 9027 9028 /* restore the merge error if any */ 9028 /* restore the merge error if any (ErrorInfo will be restored 9029 * automatically) */ 9029 9030 if (FAILED (mergeRc)) 9030 {9031 9031 rc = mergeRc; 9032 setError (mergeEi);9033 }9034 9032 } 9035 9033 while (0); … … 9039 9037 if (!aTask.subTask) 9040 9038 { 9041 /* save currenterror info */9042 ErrorInfo ei;9039 /* preserve existing error info */ 9040 ErrorInfoKeeper eik; 9043 9041 9044 9042 /* restore the machine state */ … … 9055 9053 true /* aInformCallbacksAnyway */); 9056 9054 } 9057 9058 /* restore current error info */9059 setError (ei);9060 9055 } 9061 9056 … … 9187 9182 { 9188 9183 /* here we can still safely rollback, so do it */ 9189 ErrorInfo ei; 9184 /* preserve existing error info */ 9185 ErrorInfoKeeper eik; 9190 9186 /* undo all changes */ 9191 9187 rollback (false /* aNotify */); 9192 setError (ei);9193 9188 break; 9194 9189 } … … 9306 9301 if (FAILED (rc)) 9307 9302 { 9308 ErrorInfo ei; 9303 /* preserve existing error info */ 9304 ErrorInfoKeeper eik; 9309 9305 9310 9306 if (!stateRestored) … … 9328 9324 saveSettings(); 9329 9325 } 9330 9331 setError (ei);9332 9326 } 9333 9327 -
trunk/src/VBox/Main/VirtualBoxBase.cpp
r1 r2672 641 641 //////////////////////////////////////////////////////////////////////////////// 642 642 643 /** 644 * Sets error info for the current thread. This is an internal function that 645 * gets eventually called by all public variants. If @a aPreserve is 646 * @c true, then the current error info object set on the thread before this 647 * method is called will be preserved in the IVirtualBoxErrorInfo::next 648 * attribute of the new error info object that will be then set as the 649 * current error info object. 650 */ 643 651 // static 644 HRESULT VirtualBoxSupportErrorInfoImplBase::setError ( 645 HRESULT resultCode, const GUID &iid, 646 const Bstr &component, 647 const Bstr &text) 648 { 649 LogRel (("ERROR [COM]: rc=%#08x IID={%Vuuid} component={%ls} text={%ls}\n", 650 resultCode, &iid, component.raw(), text.raw())); 652 HRESULT VirtualBoxSupportErrorInfoImplBase::setErrorInternal ( 653 HRESULT aResultCode, const GUID &aIID, 654 const Bstr &aComponent, const Bstr &aText, 655 bool aPreserve) 656 { 657 LogRel (("ERROR [COM]: aRC=%#08x aIID={%Vuuid} aComponent={%ls} aText={%ls} " 658 "aPreserve=%RTbool\n", 659 aResultCode, &aIID, aComponent.raw(), aText.raw(), aPreserve)); 651 660 652 661 /* these are mandatory, others -- not */ 653 Assert (FAILED (resultCode));654 Assert (!text.isEmpty());655 if (SUCCEEDED (resultCode) || text.isEmpty()) 656 return E_FAIL;657 658 ComObjPtr <VirtualBoxErrorInfo> info;659 HRESULT rc = info.createObject();660 if (SUCCEEDED (rc))661 {662 info->init (resultCode, iid, component, text);662 AssertReturn (FAILED (aResultCode), E_FAIL); 663 AssertReturn (!aText.isEmpty(), E_FAIL); 664 665 HRESULT rc = S_OK; 666 667 do 668 { 669 ComObjPtr <VirtualBoxErrorInfo> info; 670 rc = info.createObject(); 671 CheckComRCBreakRC (rc); 663 672 664 673 #if defined (__WIN__) 674 675 ComPtr <IVirtualBoxErrorInfo> curInfo; 676 if (aPreserve) 677 { 678 /* get the current error info if any */ 679 ComPtr <IErrorInfo> err; 680 rc = ::GetErrorInfo (0, err.asOutParam()); 681 CheckComRCBreakRC (rc); 682 rc = err.queryInterfaceTo (curInfo.asOutParam()); 683 if (FAILED (rc)) 684 { 685 /* create a IVirtualBoxErrorInfo wrapper for the native 686 * IErrorInfo object */ 687 ComObjPtr <VirtualBoxErrorInfo> wrapper; 688 rc = wrapper.createObject(); 689 if (SUCCEEDED (rc)) 690 { 691 rc = wrapper->init (err); 692 if (SUCCEEDED (rc)) 693 curInfo = wrapper; 694 } 695 } 696 } 697 /* On failure, curInfo will stay null */ 698 Assert (SUCCEEDED (rc) || curInfo.isNull()); 699 700 /* set the current error info and preserve the previous one if any */ 701 rc = info->init (aResultCode, aIID, aComponent, aText, curInfo); 702 CheckComRCBreakRC (rc); 665 703 666 704 ComPtr <IErrorInfo> err; … … 677 715 nsCOMPtr <nsIExceptionManager> em; 678 716 rc = es->GetCurrentExceptionManager (getter_AddRefs (em)); 679 if (NS_SUCCEEDED (rc)) 717 CheckComRCBreakRC (rc); 718 719 ComPtr <IVirtualBoxErrorInfo> curInfo; 720 if (aPreserve) 680 721 { 722 /* get the current error info if any */ 681 723 ComPtr <nsIException> ex; 682 rc = info.queryInterfaceTo (ex.asOutParam()); 683 if (SUCCEEDED (rc)) 684 rc = em->SetCurrentException (ex); 724 rc = em->GetCurrentException (ex.asOutParam()); 725 CheckComRCBreakRC (rc); 726 rc = ex.queryInterfaceTo (curInfo.asOutParam()); 727 if (FAILED (rc)) 728 { 729 /* create a IVirtualBoxErrorInfo wrapper for the native 730 * nsIException object */ 731 ComObjPtr <VirtualBoxErrorInfo> wrapper; 732 rc = wrapper.createObject(); 733 if (SUCCEEDED (rc)) 734 { 735 rc = wrapper->init (ex); 736 if (SUCCEEDED (rc)) 737 curInfo = wrapper; 738 } 739 } 685 740 } 741 /* On failure, curInfo will stay null */ 742 Assert (SUCCEEDED (rc) || curInfo.isNull()); 743 744 /* set the current error info and preserve the previous one if any */ 745 rc = info->init (aResultCode, aIID, aComponent, aText, curInfo); 746 CheckComRCBreakRC (rc); 747 748 ComPtr <nsIException> ex; 749 rc = info.queryInterfaceTo (ex.asOutParam()); 750 if (SUCCEEDED (rc)) 751 rc = em->SetCurrentException (ex); 686 752 } 687 753 else if (rc == NS_ERROR_UNEXPECTED) … … 705 771 #endif // !defined (__WIN__) 706 772 } 773 while (0); 707 774 708 775 AssertComRC (rc); 709 776 710 return SUCCEEDED (rc) ? resultCode : rc; 711 } 712 713 // static 714 HRESULT VirtualBoxSupportErrorInfoImplBase::setError ( 715 HRESULT resultCode, const GUID &iid, 716 const Bstr &component, 717 const char *text, va_list args) 718 { 719 return VirtualBoxSupportErrorInfoImplBase::setError ( 720 resultCode, iid, component, Utf8StrFmt (text, args)); 777 return SUCCEEDED (rc) ? aResultCode : rc; 721 778 } 722 779 -
trunk/src/VBox/Main/VirtualBoxErrorInfoImpl.cpp
r2463 r2672 26 26 //////////////////////////////////////////////////////////////////////////////// 27 27 28 voidVirtualBoxErrorInfo::init (HRESULT aResultCode, const GUID &aIID,29 const BSTR aComponent, const BSTR aText,30 IVirtualBoxErrorInfo *aNext)28 HRESULT VirtualBoxErrorInfo::init (HRESULT aResultCode, const GUID &aIID, 29 const BSTR aComponent, const BSTR aText, 30 IVirtualBoxErrorInfo *aNext) 31 31 { 32 32 mResultCode = aResultCode; … … 35 35 mText = aText; 36 36 mNext = aNext; 37 38 return S_OK; 37 39 } 38 40 … … 87 89 #if defined (__WIN__) 88 90 91 /** 92 * Initializes itself by fetching error information from the given error info 93 * object. 94 */ 95 HRESULT VirtualBoxErrorInfo::init (IErrorInfo *aInfo) 96 { 97 AssertReturn (aInfo, E_FAIL); 98 99 HRESULT rc = S_OK; 100 101 /* We don't return a failure if talking to IErrorInfo fails below to 102 * protect ourselves from bad IErrorInfo implementations (the 103 * corresponding fields will simply remain null in this case). */ 104 105 mResultCode = S_OK; 106 rc = aInfo->GetGUID (mIID.asOutParam()); 107 AssertComRC (rc); 108 rc = aInfo->GetSource (mComponent.asOutParam()); 109 AssertComRC (rc); 110 rc = aInfo->GetDescription (mText.asOutParam()); 111 AssertComRC (rc); 112 113 return S_OK; 114 } 115 89 116 // IErrorInfo methods 90 117 //////////////////////////////////////////////////////////////////////////////// … … 116 143 117 144 #else // !defined (__WIN__) 145 146 /** 147 * Initializes itself by fetching error information from the given error info 148 * object. 149 */ 150 HRESULT VirtualBoxErrorInfo::init (nsIException *aInfo) 151 { 152 AssertReturn (aInfo, E_FAIL); 153 154 HRESULT rc = S_OK; 155 156 /* We don't return a failure if talking to nsIException fails below to 157 * protect ourselves from bad nsIException implementations (the 158 * corresponding fields will simply remain null in this case). */ 159 160 rc = aInfo->GetResult (&mResultCode); 161 AssertComRC (rc); 162 Utf8Str message; 163 rc = aInfo->GetMessage (message.asOutParam()); 164 AssertComRC (rc); 165 mText = message; 166 167 return S_OK; 168 } 118 169 119 170 // nsIException methods -
trunk/src/VBox/Main/glue/ErrorInfo.cpp
r1959 r2672 20 20 */ 21 21 22 #if defined (__WIN__)23 24 #else // !defined (__WIN__)22 #if !defined (VBOX_WITH_XPCOM) 23 24 #else 25 25 26 26 #include <nsIServiceManager.h> … … 28 28 #include <nsCOMPtr.h> 29 29 30 #include <nsIInterfaceInfo.h> 31 #include <nsIInterfaceInfoManager.h> 32 33 #endif // !defined (__WIN__) 34 30 #endif 35 31 36 32 #include "VBox/com/VirtualBox.h" 37 33 #include "VBox/com/ErrorInfo.h" 38 34 #include "VBox/com/assert.h" 35 #include "VBox/com/com.h" 39 36 40 37 #include <iprt/stream.h> 41 38 #include <iprt/string.h> 39 42 40 #include <VBox/err.h> 43 41 44 /**45 * Resolves a given interface ID to a string containint interface name.46 * If, for some reason, the given IID cannot be resolved to a name,47 * a NULL string is returned. A non-NULL interface name must be freed48 * using SysFreeString().49 */50 static void GetInterfaceNameByIID (const GUID &id, BSTR *name)51 {52 Assert (name);53 if (!name)54 return;55 56 *name = NULL;57 58 #if defined (__WIN__)59 60 LONG rc;61 LPOLESTR iidStr = NULL;62 if (StringFromIID (id, &iidStr) == S_OK)63 {64 HKEY ifaceKey;65 rc = RegOpenKeyExW (HKEY_CLASSES_ROOT, L"Interface", 0, KEY_QUERY_VALUE, &ifaceKey);66 if (rc == ERROR_SUCCESS)67 {68 HKEY iidKey;69 rc = RegOpenKeyExW (ifaceKey, iidStr, 0, KEY_QUERY_VALUE, &iidKey);70 if (rc == ERROR_SUCCESS)71 {72 // determine the size and type73 DWORD sz, type;74 rc = RegQueryValueExW (iidKey, NULL, NULL, &type, NULL, &sz);75 if (rc == ERROR_SUCCESS && type == REG_SZ)76 {77 // query the value to BSTR78 *name = SysAllocStringLen (NULL, (sz + 1) / sizeof (TCHAR) + 1);79 rc = RegQueryValueExW (iidKey, NULL, NULL, NULL, (LPBYTE) *name, &sz);80 if (rc != ERROR_SUCCESS)81 {82 SysFreeString (*name);83 name = NULL;84 }85 }86 RegCloseKey (iidKey);87 }88 RegCloseKey (ifaceKey);89 }90 CoTaskMemFree (iidStr);91 }92 93 #else94 95 nsresult rv;96 nsCOMPtr <nsIInterfaceInfoManager> iim =97 do_GetService (NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv);98 if (NS_SUCCEEDED (rv))99 {100 nsCOMPtr <nsIInterfaceInfo> iinfo;101 rv = iim->GetInfoForIID (&id, getter_AddRefs (iinfo));102 if (NS_SUCCEEDED (rv))103 {104 const char *iname = NULL;105 iinfo->GetNameShared (&iname);106 char *utf8IName = NULL;107 if (VBOX_SUCCESS (RTStrCurrentCPToUtf8 (&utf8IName, iname)))108 {109 PRTUCS2 ucs2IName = NULL;110 if (VBOX_SUCCESS (RTStrUtf8ToUcs2 (&ucs2IName, utf8IName)))111 {112 *name = SysAllocString ((OLECHAR *) ucs2IName);113 RTStrUcs2Free (ucs2IName);114 }115 RTStrFree (utf8IName);116 }117 }118 }119 120 #endif121 }122 123 124 42 namespace com 125 43 { 126 44 127 // IErrorInfo class45 // ErrorInfo class 128 46 //////////////////////////////////////////////////////////////////////////////// 129 47 130 void ErrorInfo::init ( )48 void ErrorInfo::init (bool aKeepObj /* = false */) 131 49 { 132 50 HRESULT rc = E_FAIL; 133 51 134 #if defined (__WIN__)52 #if !defined (VBOX_WITH_XPCOM) 135 53 136 54 ComPtr <IErrorInfo> err; … … 138 56 if (rc == S_OK && err) 139 57 { 58 if (aKeepObj) 59 mErrorInfo = err; 60 140 61 ComPtr <IVirtualBoxErrorInfo> info; 141 62 rc = err.queryInterfaceTo (info.asOutParam()); … … 165 86 } 166 87 167 #else // !defined ( __WIN__)88 #else // !defined (VBOX_WITH_XPCOM) 168 89 169 90 nsCOMPtr <nsIExceptionService> es; … … 179 100 if (NS_SUCCEEDED (rc) && ex) 180 101 { 102 if (aKeepObj) 103 mErrorInfo = ex; 104 181 105 ComPtr <IVirtualBoxErrorInfo> info; 182 106 rc = ex.queryInterfaceTo (info.asOutParam()); … … 213 137 AssertComRC (rc); 214 138 215 #endif // !defined ( __WIN__)216 } 217 218 void ErrorInfo::init (IUnknown * i, const GUID &iid)219 { 220 Assert ( i);221 if (! i)139 #endif // !defined (VBOX_WITH_XPCOM) 140 } 141 142 void ErrorInfo::init (IUnknown *aI, const GUID &aIID, bool aKeepObj /* = false */) 143 { 144 Assert (aI); 145 if (!aI) 222 146 return; 223 147 224 #if defined (__WIN__)225 226 ComPtr <IUnknown> iface = i;148 #if !defined (VBOX_WITH_XPCOM) 149 150 ComPtr <IUnknown> iface = aI; 227 151 ComPtr <ISupportErrorInfo> serr; 228 152 HRESULT rc = iface.queryInterfaceTo (serr.asOutParam()); 229 153 if (SUCCEEDED (rc)) 230 154 { 231 rc = serr->InterfaceSupportsErrorInfo ( iid);155 rc = serr->InterfaceSupportsErrorInfo (aIID); 232 156 if (SUCCEEDED (rc)) 233 init ();234 } 235 236 #else // !defined (__WIN__)237 238 init ();239 240 #endif // !defined (__WIN__)157 init (aKeepObj); 158 } 159 160 #else 161 162 init (aKeepObj); 163 164 #endif 241 165 242 166 if (mIsBasicAvailable) 243 167 { 244 mCalleeIID = iid;245 GetInterfaceNameByIID ( iid, mCalleeName.asOutParam());168 mCalleeIID = aIID; 169 GetInterfaceNameByIID (aIID, mCalleeName.asOutParam()); 246 170 } 247 171 } … … 270 194 271 195 rc = info->COMGETTER(Text) (mText.asOutParam()); 196 gotSomething |= SUCCEEDED (rc); 197 gotAll &= SUCCEEDED (rc); 198 199 ComPtr <IVirtualBoxErrorInfo> next; 200 rc = info->COMGETTER(Next) (next.asOutParam()); 201 if (SUCCEEDED (rc) && !next.isNull()) 202 { 203 mNext.reset (new ErrorInfo (next)); 204 Assert (mNext.get()); 205 if (!mNext.get()) 206 rc = E_OUTOFMEMORY; 207 } 208 else 209 mNext.reset(); 272 210 gotSomething |= SUCCEEDED (rc); 273 211 gotAll &= SUCCEEDED (rc); … … 300 238 } 301 239 302 // IErrorInfo class 240 /** 241 * Sets the given error info object for the current thread. If @a aPreserve 242 * is @c true, then the current error info set on the thread before this 243 * method is called will be preserved in the IVirtualBoxErrorInfo::next 244 * attribute of the new error info object that will be then set as the 245 * current error info object. 246 */ 247 248 //static 249 HRESULT setError (IVirtualBoxErrorInfo *aInfo); 250 251 // ProgressErrorInfo class 303 252 //////////////////////////////////////////////////////////////////////////////// 304 253 305 254 ProgressErrorInfo::ProgressErrorInfo (IProgress *progress) : 306 ErrorInfo ( true)255 ErrorInfo (false /* aDummy */) 307 256 { 308 257 Assert (progress); … … 316 265 } 317 266 267 // ErrorInfoKeeper class 268 //////////////////////////////////////////////////////////////////////////////// 269 270 HRESULT ErrorInfoKeeper::restore() 271 { 272 if (mForgot) 273 return S_OK; 274 275 HRESULT rc = S_OK; 276 277 #if !defined (VBOX_WITH_XPCOM) 278 279 ComPtr <IErrorInfo> err; 280 if (!mErrorInfo.isNull()) 281 { 282 rc = mErrorInfo.queryInterfaceTo (err.asOutParam()); 283 AssertComRC (rc); 284 } 285 rc = ::SetErrorInfo (0, err); 286 287 #else // !defined (VBOX_WITH_XPCOM) 288 289 nsCOMPtr <nsIExceptionService> es; 290 es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc); 291 if (NS_SUCCEEDED (rc)) 292 { 293 nsCOMPtr <nsIExceptionManager> em; 294 rc = es->GetCurrentExceptionManager (getter_AddRefs (em)); 295 if (NS_SUCCEEDED (rc)) 296 { 297 ComPtr <nsIException> ex; 298 if (!mErrorInfo.isNull()) 299 { 300 rc = mErrorInfo.queryInterfaceTo (ex.asOutParam()); 301 AssertComRC (rc); 302 } 303 rc = em->SetCurrentException (ex); 304 } 305 } 306 307 #endif // !defined (VBOX_WITH_XPCOM) 308 309 if (SUCCEEDED (rc)) 310 { 311 mErrorInfo.setNull(); 312 mForgot = true; 313 } 314 315 return rc; 316 } 317 318 318 }; // namespace com 319 319 -
trunk/src/VBox/Main/glue/com.cpp
r1 r2672 20 20 */ 21 21 22 #if defined (__WIN__)22 #if !defined (VBOX_WITH_XPCOM) 23 23 24 24 #include <objbase.h> 25 25 26 #else // !defined (__WIN__)26 #else 27 27 28 28 #include <stdlib.h> … … 36 36 #include <nsEventQueueUtils.h> 37 37 38 #endif // !defined (__WIN__) 38 #include <nsIInterfaceInfo.h> 39 #include <nsIInterfaceInfoManager.h> 40 41 #endif 42 43 #include <iprt/string.h> 44 #include <VBox/err.h> 39 45 40 46 #include "VBox/com/com.h" … … 48 54 HRESULT rc = E_FAIL; 49 55 50 #if defined (__WIN__) 56 #if !defined (VBOX_WITH_XPCOM) 57 51 58 rc = CoInitializeEx (NULL, COINIT_MULTITHREADED | 52 59 COINIT_DISABLE_OLE1DDE | 53 60 COINIT_SPEED_OVER_MEMORY); 54 #else 55 /* 56 * Set VBOX_XPCOM_HOME if not present 57 */61 62 #else 63 64 /* Set VBOX_XPCOM_HOME if not present */ 58 65 if (!getenv("VBOX_XPCOM_HOME")) 59 66 { … … 82 89 } 83 90 } 91 84 92 #endif 85 93 … … 91 99 void Shutdown() 92 100 { 93 #if defined (__WIN__) 101 #if !defined (VBOX_WITH_XPCOM) 102 94 103 CoUninitialize(); 95 #else 104 105 #else 106 96 107 nsCOMPtr <nsIEventQueue> eventQ; 97 108 nsresult rc = NS_GetMainEventQ (getter_AddRefs (eventQ)); … … 100 111 BOOL isOnMainThread = FALSE; 101 112 eventQ->IsOnCurrentThread (&isOnMainThread); 102 eventQ = nsnull; / / early release113 eventQ = nsnull; /* early release */ 103 114 if (isOnMainThread) 104 115 { 105 / / only the main thread needs to uninitialize XPCOM116 /* only the main thread needs to uninitialize XPCOM */ 106 117 NS_ShutdownXPCOM (nsnull); 107 118 XPCOMGlueShutdown(); 108 119 } 109 120 } 121 110 122 #endif 111 123 } 112 124 125 void GetInterfaceNameByIID (const GUID &aIID, BSTR *aName) 126 { 127 Assert (aName); 128 if (!aName) 129 return; 130 131 *aName = NULL; 132 133 #if !defined (VBOX_WITH_XPCOM) 134 135 LONG rc; 136 LPOLESTR iidStr = NULL; 137 if (StringFromIID (aIID, &iidStr) == S_OK) 138 { 139 HKEY ifaceKey; 140 rc = RegOpenKeyExW (HKEY_CLASSES_ROOT, L"Interface", 141 0, KEY_QUERY_VALUE, &ifaceKey); 142 if (rc == ERROR_SUCCESS) 143 { 144 HKEY iidKey; 145 rc = RegOpenKeyExW (ifaceKey, iidStr, 0, KEY_QUERY_VALUE, &iidKey); 146 if (rc == ERROR_SUCCESS) 147 { 148 /* determine the size and type */ 149 DWORD sz, type; 150 rc = RegQueryValueExW (iidKey, NULL, NULL, &type, NULL, &sz); 151 if (rc == ERROR_SUCCESS && type == REG_SZ) 152 { 153 /* query the value to BSTR */ 154 *aName = SysAllocStringLen (NULL, (sz + 1) / 155 sizeof (TCHAR) + 1); 156 rc = RegQueryValueExW (iidKey, NULL, NULL, NULL, 157 (LPBYTE) *aName, &sz); 158 if (rc != ERROR_SUCCESS) 159 { 160 SysFreeString (*aName); 161 aName = NULL; 162 } 163 } 164 RegCloseKey (iidKey); 165 } 166 RegCloseKey (ifaceKey); 167 } 168 CoTaskMemFree (iidStr); 169 } 170 171 #else 172 173 nsresult rv; 174 nsCOMPtr <nsIInterfaceInfoManager> iim = 175 do_GetService (NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv); 176 if (NS_SUCCEEDED (rv)) 177 { 178 nsCOMPtr <nsIInterfaceInfo> iinfo; 179 rv = iim->GetInfoForIID (&aIID, getter_AddRefs (iinfo)); 180 if (NS_SUCCEEDED (rv)) 181 { 182 const char *iname = NULL; 183 iinfo->GetNameShared (&iname); 184 char *utf8IName = NULL; 185 if (VBOX_SUCCESS (RTStrCurrentCPToUtf8 (&utf8IName, iname))) 186 { 187 PRTUCS2 ucs2IName = NULL; 188 if (VBOX_SUCCESS (RTStrUtf8ToUcs2 (&ucs2IName, utf8IName))) 189 { 190 *aName = SysAllocString ((OLECHAR *) ucs2IName); 191 RTStrUcs2Free (ucs2IName); 192 } 193 RTStrFree (utf8IName); 194 } 195 } 196 } 197 198 #endif 199 } 200 113 201 }; // namespace com -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r2602 r2672 365 365 Sometimes invocation of some component's method may involve 366 366 methods of other components that may also fail (independently of 367 this method's failure), or a series of non-fatal errors may precede 368 a fatal error that causes method failure. In cases like that, it 369 may be desirable to preserve information about all errors happened 370 during method invocation and deliver it to the caller. The <link 371 to="#next"/> attribute is intended specifically for this purpose 372 and allows to represent a chain of errors through a single 373 IVirtualBoxErrorInfo instance set after method invocation. 367 this method's failure), or a series of non-fatal errors may 368 precede a fatal error that causes method failure. In cases like 369 that, it may be desirable to preserve information about all errors 370 happened during method invocation and deliver it to the 371 caller. The <link to="#next"/> attribute is intended specifically 372 for this purpose and allows to represent a chain of errors through 373 a single IVirtualBoxErrorInfo instance set after method 374 invocation. Note that errors are stored to a chain in the reverse 375 order, i.e. the initial error object you query right after method 376 invocation is the last error set by the callee, the object it 377 points to in the @a next attribute is the previous error and so 378 on, up to the first error (which is the last in the chain). 374 379 </desc> 375 380 -
trunk/src/VBox/Main/include/VirtualBoxBase.h
r357 r2672 1032 1032 class VirtualBoxSupportErrorInfoImplBase 1033 1033 { 1034 static HRESULT setErrorInternal (HRESULT aResultCode, const GUID &aIID, 1035 const Bstr &aComponent, const Bstr &aText, 1036 bool aPreserve); 1037 1034 1038 protected: 1035 1039 1036 static HRESULT setError (HRESULT resultCode, const GUID &iid, 1037 const Bstr &component, 1038 const Bstr &text); 1039 1040 static HRESULT setError (HRESULT resultCode, const GUID &iid, 1041 const Bstr &component, 1042 const char *text, va_list args); 1043 1044 inline static HRESULT setError (const com::ErrorInfo &ei) 1045 { 1046 if (!ei.isBasicAvailable()) 1047 return S_OK; 1048 1049 Assert (FAILED (ei.getResultCode())); 1050 Assert (!ei.getText().isEmpty()); 1051 return setError (ei.getResultCode(), ei.getInterfaceID(), 1052 ei.getComponent(), ei.getText()); 1040 inline static HRESULT setError (HRESULT aResultCode, const GUID &aIID, 1041 const Bstr &aComponent, 1042 const Bstr &aText) 1043 { 1044 return setErrorInternal (aResultCode, aIID, aComponent, aText, 1045 false /* aPreserve */); 1046 } 1047 1048 inline static HRESULT addError (HRESULT aResultCode, const GUID &aIID, 1049 const Bstr &aComponent, 1050 const Bstr &aText) 1051 { 1052 return setErrorInternal (aResultCode, aIID, aComponent, aText, 1053 true /* aPreserve */); 1054 } 1055 1056 static HRESULT setError (HRESULT aResultCode, const GUID &aIID, 1057 const Bstr &aComponent, 1058 const char *aText, va_list aArgs) 1059 { 1060 return setErrorInternal (aResultCode, aIID, aComponent, 1061 Utf8StrFmt (aText, aArgs), 1062 false /* aPreserve */); 1063 } 1064 1065 static HRESULT addError (HRESULT aResultCode, const GUID &aIID, 1066 const Bstr &aComponent, 1067 const char *aText, va_list aArgs) 1068 { 1069 return setErrorInternal (aResultCode, aIID, aComponent, 1070 Utf8StrFmt (aText, aArgs), 1071 true /* aPreserve */); 1053 1072 } 1054 1073 }; … … 1150 1169 * #setError (HRESULT, const char *, ...) for an example. 1151 1170 * 1152 * @param resultCoderesult (error) code, must not be S_OK1153 * @param iidIID of the intrface that defines the error1154 * @param componentname of the component that generates the error1155 * @param texterror message (must not be null), an RTStrPrintf-like1171 * @param aResultCode result (error) code, must not be S_OK 1172 * @param aIID IID of the intrface that defines the error 1173 * @param aComponent name of the component that generates the error 1174 * @param aText error message (must not be null), an RTStrPrintf-like 1156 1175 * format string in UTF-8 encoding 1157 1176 * @param ... list of arguments for the format string … … 1162 1181 * error argument. 1163 1182 */ 1164 inline static HRESULT setError (HRESULT resultCode, const GUID &iid,1165 const wchar_t * component,1166 const char * text, ...)1183 inline static HRESULT setError (HRESULT aResultCode, const GUID &aIID, 1184 const wchar_t *aComponent, 1185 const char *aText, ...) 1167 1186 { 1168 1187 va_list args; 1169 va_start (args, text); 1170 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError ( 1171 resultCode, iid, component, text, args); 1188 va_start (args, aText); 1189 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError 1190 (aResultCode, aIID, aComponent, aText, args); 1191 va_end (args); 1192 return rc; 1193 } 1194 1195 /** 1196 * This method is the same as #setError() except that it preserves the 1197 * error info object (if any) set for the current thread before this 1198 * method is called by storing it in the IVirtualBoxErrorInfo::next 1199 * attribute of the new error info object. 1200 */ 1201 inline static HRESULT addError (HRESULT aResultCode, const GUID &aIID, 1202 const wchar_t *aComponent, 1203 const char *aText, ...) 1204 { 1205 va_list args; 1206 va_start (args, aText); 1207 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError 1208 (aResultCode, aIID, aComponent, aText, args); 1172 1209 va_end (args); 1173 1210 return rc; … … 1197 1234 * </code> 1198 1235 */ 1199 inline static HRESULT setError (HRESULT resultCode, const char *text, ...)1236 inline static HRESULT setError (HRESULT aResultCode, const char *aText, ...) 1200 1237 { 1201 1238 va_list args; 1202 va_start (args, text); 1203 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError ( 1204 resultCode, COM_IIDOF(I), C::getComponentName(), text, args); 1239 va_start (args, aText); 1240 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError 1241 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args); 1242 va_end (args); 1243 return rc; 1244 } 1245 1246 /** 1247 * This method is the same as #setError() except that it preserves the 1248 * error info object (if any) set for the current thread before this 1249 * method is called by storing it in the IVirtualBoxErrorInfo::next 1250 * attribute of the new error info object. 1251 */ 1252 inline static HRESULT addError (HRESULT aResultCode, const char *aText, ...) 1253 { 1254 va_list args; 1255 va_start (args, aText); 1256 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError 1257 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, args); 1205 1258 va_end (args); 1206 1259 return rc; … … 1216 1269 * and #setError (HRESULT, const char *, ...) for details. 1217 1270 */ 1218 inline static HRESULT setErrorV (HRESULT resultCode, const char *text, va_list args) 1219 { 1220 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError ( 1221 resultCode, COM_IIDOF(I), C::getComponentName(), text, args); 1271 inline static HRESULT setErrorV (HRESULT aResultCode, const char *aText, 1272 va_list aArgs) 1273 { 1274 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError 1275 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs); 1276 return rc; 1277 } 1278 1279 /** 1280 * This method is the same as #setErrorV() except that it preserves the 1281 * error info object (if any) set for the current thread before this 1282 * method is called by storing it in the IVirtualBoxErrorInfo::next 1283 * attribute of the new error info object. 1284 */ 1285 inline static HRESULT addErrorV (HRESULT aResultCode, const char *aText, 1286 va_list aArgs) 1287 { 1288 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError 1289 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText, aArgs); 1222 1290 return rc; 1223 1291 } … … 1235 1303 * and #setError (HRESULT, const char *, ...) for details. 1236 1304 */ 1237 inline static HRESULT setErrorBstr (HRESULT resultCode, const Bstr &text) 1238 { 1239 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError ( 1240 resultCode, COM_IIDOF(I), C::getComponentName(), text); 1305 inline static HRESULT setErrorBstr (HRESULT aResultCode, const Bstr &aText) 1306 { 1307 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError 1308 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText); 1309 return rc; 1310 } 1311 1312 /** 1313 * This method is the same as #setErrorBstr() except that it preserves the 1314 * error info object (if any) set for the current thread before this 1315 * method is called by storing it in the IVirtualBoxErrorInfo::next 1316 * attribute of the new error info object. 1317 */ 1318 inline static HRESULT addErrorBstr (HRESULT aResultCode, const Bstr &aText) 1319 { 1320 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError 1321 (aResultCode, COM_IIDOF(I), C::getComponentName(), aText); 1241 1322 return rc; 1242 1323 } … … 1251 1332 * for details. 1252 1333 */ 1253 inline static HRESULT setError (HRESULT resultCode, const GUID &iid,1254 const char * text, ...)1334 inline static HRESULT setError (HRESULT aResultCode, const GUID &aIID, 1335 const char *aText, ...) 1255 1336 { 1256 1337 va_list args; 1257 va_start (args, text);1258 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError (1259 resultCode, iid, C::getComponentName(), text, args);1338 va_start (args, aText); 1339 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::setError 1340 (aResultCode, aIID, C::getComponentName(), aText, args); 1260 1341 va_end (args); 1261 1342 return rc; … … 1263 1344 1264 1345 /** 1265 * Sets the error information for the current thread using the error 1266 * information previously fetched using an ErrorInfo instance. 1267 * This is useful, for instance, if you want to keep the error information 1268 * returned by some interface's method, but need to call another method 1269 * of some interface prior to returning from your method (calling 1270 * another method will normally reset the current error information). 1271 */ 1272 inline static HRESULT setError (const com::ErrorInfo &ei) 1273 { 1274 return VirtualBoxSupportErrorInfoImplBase::setError (ei); 1346 * This method is the same as #setError() except that it preserves the 1347 * error info object (if any) set for the current thread before this 1348 * method is called by storing it in the IVirtualBoxErrorInfo::next 1349 * attribute of the new error info object. 1350 */ 1351 inline static HRESULT addError (HRESULT aResultCode, const GUID &aIID, 1352 const char *aText, ...) 1353 { 1354 va_list args; 1355 va_start (args, aText); 1356 HRESULT rc = VirtualBoxSupportErrorInfoImplBase::addError 1357 (aResultCode, aIID, C::getComponentName(), aText, args); 1358 va_end (args); 1359 return rc; 1275 1360 } 1276 1361 -
trunk/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h
r2463 r2672 49 49 50 50 #if defined (__WIN__) 51 52 HRESULT init (IErrorInfo *aInfo); 53 51 54 STDMETHOD(GetGUID) (GUID *guid); 52 55 STDMETHOD(GetSource) (BSTR *source); … … 54 57 STDMETHOD(GetHelpFile) (BSTR *pBstrHelpFile); 55 58 STDMETHOD(GetHelpContext) (DWORD *pdwHelpContext); 59 56 60 #else // !defined (__WIN__) 61 62 HRESULT init (nsIException *aInfo); 63 57 64 NS_DECL_NSIEXCEPTION 65 58 66 #endif 59 67 … … 61 69 62 70 // public initializer/uninitializer for internal purposes only 63 voidinit (HRESULT aResultCode, const GUID &aIID,64 const BSTR aComponent, const BSTR aText,65 IVirtualBoxErrorInfo *aNext = NULL);71 HRESULT init (HRESULT aResultCode, const GUID &aIID, 72 const BSTR aComponent, const BSTR aText, 73 IVirtualBoxErrorInfo *aNext = NULL); 66 74 67 75 // IVirtualBoxErrorInfo properties
Note:
See TracChangeset
for help on using the changeset viewer.

