static object ComInterfaceToObjectInternal_NoManagedUnboxing( IntPtr pComItf, RuntimeTypeHandle interfaceType, RuntimeTypeHandle classTypeInSignature, CreateComObjectFlags flags) { if (pComItf == default(IntPtr)) { return(null); } // // Is this a CCW? // ComCallableObject ccw; if (ComCallableObject.TryGetCCW(pComItf, out ccw)) { return(ccw.TargetObject); } // // This pointer is not a CCW, but we need to do one additional check here for aggregation // In case the COM pointer is a interface implementation from native, but the outer object is a // managed object // IntPtr pComIdentityIUnknown = McgMarshal.ComQueryInterfaceNoThrow(pComItf, ref Interop.COM.IID_IUnknown); if (pComIdentityIUnknown == default(IntPtr)) { throw new InvalidCastException(); } try { // // Check whether the identity COM pointer to see if it is a aggregating CCW // if (ComCallableObject.TryGetCCW(pComIdentityIUnknown, out ccw)) { return(ccw.TargetObject); } // // Nope, not a CCW - let's go down our RCW creation code path // return(ComInterfaceToComObjectInternal( pComItf, pComIdentityIUnknown, interfaceType, classTypeInSignature, ContextCookie.Default, flags )); } finally { McgMarshal.ComRelease(pComIdentityIUnknown); } }
private static unsafe IntPtr ManagedObjectToComInterfaceInternal(Object obj, ref Guid iid, RuntimeTypeHandle interfaceType) { if (obj == null) { return(default(IntPtr)); } // // Look up ComCallableObject from the cache // If couldn't find one, create a new one // ComCallableObject ccw = null; try { // // Either return existing one or create a new one // In either case, the returned CCW is addref-ed to avoid race condition // IntPtr dummy; ccw = CCWLookupMap.GetOrCreateCCW(obj, interfaceType, out dummy); Debug.Assert(ccw != null); return(ccw.GetComInterfaceForIID(ref iid, interfaceType)); } finally { // // Free the extra ref count added by GetOrCreateCCW (to protect the CCW from being collected) // if (ccw != null) { ccw.Release(); } } }
/// <summary> /// This method returns a new Exception object given the HR value. /// /// 1. We check whether we have our own LanguageException associated with this hr. If so we simply use it since it helps preserve the stacktrace, message and type. /// This is done using GetLanguageException API on ILanguageExceptionErrorInfo from IRestrictedErrorInfo. Since ILanguageExceptionErrorInfo is available only on Windows Blue /// we can only do this WindowsBlue and above. In desktop CLR we could use GetErroInfo and check whether we have our IErroInfo and retrieve our own exception. /// For Win8 in .NET Native we simply create the exception using the RestrictedErrorInfo and hence only able to give the exception with restrictedErrorMsg. /// 2. In case we do not have the languageException we simply check RestrictedErrorInfo for errorMsg and create an exception using /// <errorMsg>\r\n<restrictedErrorMsg>. This is done for only windows blue. To be backward compatible we only use errorMsg for creating exception in win8. /// 3. PS - This class puts all the logic in try, catch block to ensure that none of the exception helpers /// throw exception themselves. /// </summary> /// <param name="hr"></param> /// <param name="isWinRTScenario"></param> internal static Exception GetExceptionForHRInternalNoThrow(int hr, bool isWinRTScenario, bool isClassicCOM) { Exception ex; IntPtr pRestrictedErrorInfo = IntPtr.Zero; try { if (TryGetRestrictedErrorInfo(out pRestrictedErrorInfo)) { // This is to check whether we need to give post win8 behavior or not. if (isWinRTScenario) { // Check whether the given IRestrictedErrorInfo object supports ILanguageExceptionErrorInfo IntPtr pLanguageExceptionErrorInfo = McgMarshal.ComQueryInterfaceNoThrow(pRestrictedErrorInfo, ref Interop.COM.IID_ILanguageExceptionErrorInfo); if (pLanguageExceptionErrorInfo != IntPtr.Zero) { // We have an LanguageExceptionErrorInfo. IntPtr pUnk; __com_ILanguageExceptionErrorInfo *pComLanguageExceptionErrorInfo = (__com_ILanguageExceptionErrorInfo *)pLanguageExceptionErrorInfo; int result = CalliIntrinsics.StdCall <int>(pComLanguageExceptionErrorInfo->pVtable->pfnGetLanguageException, pLanguageExceptionErrorInfo, out pUnk); McgMarshal.ComSafeRelease(pLanguageExceptionErrorInfo); if (result >= 0 && pUnk != IntPtr.Zero) { try { // Check whether the given pUnk is a managed exception. ComCallableObject ccw; if (ComCallableObject.TryGetCCW(pUnk, out ccw)) { return(ccw.TargetObject as Exception); } } finally { McgMarshal.ComSafeRelease(pUnk); } } } } String message = null, errorInfoReference = null; string errMsg, errCapSid, resErrMsg; int errHr; object restrictedErrorInfo = null; bool hasErrorInfo = false; if (RestrictedErrorInfoHelper.GetErrorDetails(pRestrictedErrorInfo, out errMsg, out errHr, out resErrMsg, out errCapSid) && errHr == hr) { // RestrictedErrorInfo details can be used since the pRestrictedErrorInfo has the same hr value as the hr returned by the native code. // We are in windows blue or above and hence the exceptionMsg is errMsg + "\r\n" + resErrMsg message = String.IsNullOrEmpty(resErrMsg) ? errMsg : errMsg + "\r\n" + resErrMsg; RestrictedErrorInfoHelper.GetReference(pRestrictedErrorInfo, out errorInfoReference); restrictedErrorInfo = McgMarshal.ComInterfaceToObject(pRestrictedErrorInfo, InternalTypes.IRestrictedErrorInfo); hasErrorInfo = true; } if (hr == Interop.COM.RO_E_CLOSED && isWinRTScenario) { hr = Interop.COM.COR_E_OBJECTDISPOSED; } // Now we simply need to set the description and the resDescription by adding an internal method. ex = GetMappingExceptionForHR(hr, message, isClassicCOM, hasErrorInfo); if (restrictedErrorInfo != null) { InteropExtensions.AddExceptionDataForRestrictedErrorInfo(ex, resErrMsg, errorInfoReference, errCapSid, restrictedErrorInfo); } return(ex); } } catch (Exception) { // We can't do any thing here and hence we swallow the exception and get the corresponding hr. } finally { McgMarshal.ComSafeRelease(pRestrictedErrorInfo); } // We could not find any restrictedErrorInfo associated with this object and hence we simply use the hr to create the exception. return(GetMappingExceptionForHR(hr, null, isClassicCOM, hasErrorInfo: false)); }
internal static int OnDependentWrapperCallback(ComCallableObject ccw) { __ComObject rcw = s_currentComObjectToWalk; // // Skip dependent handle creation if RCW/CCW points to the same managed object // if (rcw == ccw.TargetObject) return Interop.COM.S_OK; // // Avoid touching CCW target object that have already been GC collected // if (ccw.TargetObject == null) return Interop.COM.S_OK; // // Allocate (or use existing) a dependent handle for RCW->CCW // if (!s_dependentHandleList.AllocateHandle(rcw, ccw)) return Interop.COM.E_FAIL; return Interop.COM.S_OK; }