/// <summary> /// Returns runtime class name for a specific object /// </summary> internal static string GetRuntimeClassName(Object obj) { #if ENABLE_WINRT System.IntPtr pWinRTItf = default(IntPtr); try { pWinRTItf = McgMarshal.ObjectToIInspectable(obj); if (pWinRTItf == default(IntPtr)) { return(String.Empty); } else { return(GetRuntimeClassName(pWinRTItf)); } } finally { if (pWinRTItf != default(IntPtr)) { McgMarshal.ComRelease(pWinRTItf); } } #else throw new PlatformNotSupportedException("GetRuntimeClassName"); #endif }
/// <summary> /// Returns runtime class name for a specific WinRT interface /// </summary> internal static string GetRuntimeClassName(IntPtr pWinRTItf) { #if ENABLE_MIN_WINRT void *unsafe_hstring = null; try { int hr = CalliIntrinsics.StdCall__int( ((__com_IInspectable *)(void *)pWinRTItf)->pVtable->pfnGetRuntimeClassName, pWinRTItf, &unsafe_hstring); // Don't throw if the call fails if (hr < 0) { return(String.Empty); } return(McgMarshal.HStringToString(new IntPtr(unsafe_hstring))); } finally { if (unsafe_hstring != null) { McgMarshal.FreeHString(new IntPtr(unsafe_hstring)); } } #else throw new PlatformNotSupportedException("GetRuntimeClassName(IntPtr)"); #endif }
internal static void GetReference(System.IntPtr pRestrictedErrorInfo, out string errReference) { Debug.Assert(pRestrictedErrorInfo != IntPtr.Zero); IntPtr pReference = IntPtr.Zero; errReference = null; try { __com_IRestrictedErrorInfo *pComRestrictedErrorInfo = (__com_IRestrictedErrorInfo *)pRestrictedErrorInfo; int result = CalliIntrinsics.StdCall__int(pComRestrictedErrorInfo->pVtable->pfnGetReference, pRestrictedErrorInfo, out pReference); if (result >= 0) { errReference = Interop.COM.ConvertBSTRToString(pReference); } else { errReference = null; } } finally { if (pReference != IntPtr.Zero) { McgMarshal.SysFreeString(pReference); } } }
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); } }
public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type t) { if (o == null) { throw new ArgumentNullException("o"); } if (t == null) { throw new ArgumentNullException("type"); } RuntimeTypeHandle interfaceTypeHandle = t.TypeHandle; McgTypeInfo secondTypeInfo; McgTypeInfo mcgTypeInfo = McgModuleManager.GetTypeInfoFromTypeHandle(interfaceTypeHandle, out secondTypeInfo); if (mcgTypeInfo.IsNull) { #if CORECLR return(default(IntPtr)); #else throw new MissingInteropDataException(SR.ComTypeMarshalling_MissingInteropData, t); #endif } return(McgMarshal.ObjectToComInterface(o, mcgTypeInfo)); }
/// <summary> /// This method validates that the given weak reference is alive. /// 1. IWeakReference->Resolve method returns the target's interface for the mapping IID passed to it. /// 2. If the object is not alive it returns null. /// 2. From the returned interface we get or create a new RCW and return it. /// </summary> /// <returns></returns> internal unsafe object Resolve() { IntPtr pInspectable; __com_IWeakReference *pComIWeakReference = (__com_IWeakReference *)m_pComWeakRef; Guid inspectableIID = Interop.COM.IID_IInspectable; int result = CalliIntrinsics.StdCall__int( pComIWeakReference->pVtable->pfnResolve, m_pComWeakRef, &inspectableIID, &pInspectable); if (result >= 0 && pInspectable != IntPtr.Zero) { try { return(McgMarshal.ComInterfaceToObject(pInspectable, McgModuleManager.IInspectable)); } finally { // Release the pInspectable. McgMarshal.ComRelease(pInspectable); } } return(null); }
/// <summary> /// The method calls RoOriginateLanguageException. The method has all the logic in try, catch block to ensure that none of the exception helpers /// throw exception themselves. /// </summary> /// <param name="ex"></param> /// <returns></returns> private static bool OriginateLanguageException(Exception ex) { IntPtr pUnk = IntPtr.Zero; HSTRING errorMsg = default(HSTRING); try { pUnk = McgMarshal.ObjectToComInterface(ex, InternalTypes.IUnknown); if (pUnk != IntPtr.Zero) { RuntimeAugments.GenerateExceptionInformationForDump(ex, pUnk); errorMsg = McgMarshal.StringToHString(ex.Message); return(ExternalInterop.RoOriginateLanguageException(ex.HResult, errorMsg, pUnk) >= 0); } } catch (Exception) { // We can't do anything here and hence simply swallow the exception } finally { McgMarshal.ComSafeRelease(pUnk); if (errorMsg.handle != IntPtr.Zero) { ExternalInterop.WindowsDeleteString(errorMsg.handle.ToPointer()); } } return(false); }
/// <summary> /// Returns runtime class name for a specific object /// </summary> internal static string GetRuntimeClassName(Object obj) { #if ENABLE_MIN_WINRT System.IntPtr pWinRTItf = default(IntPtr); try { pWinRTItf = McgMarshal.ObjectToIInspectable(obj); if (pWinRTItf == default(IntPtr)) { return(String.Empty); } else { return(GetRuntimeClassName(pWinRTItf)); } } finally { if (pWinRTItf != default(IntPtr)) { McgMarshal.ComRelease(pWinRTItf); } } #else return(string.Empty); #endif }
public int CreateInstance(IntPtr pUnkOuter, Guid *riid, IntPtr *ppv) { if (pUnkOuter != IntPtr.Zero) { // We do not currently support COM aggregation return(Interop.COM.CLASS_E_NOAGGREGATION); } RuntimeTypeHandle interfaceTypeHandle = parent.GetTypeFromGuid(ref *riid); if (interfaceTypeHandle.Equals(default(RuntimeTypeHandle))) { return(Interop.COM.E_NOINTERFACE); } else { object result = InteropExtensions.RuntimeNewObject(classType); * ppv = McgMarshal.ObjectToComInterface(result, interfaceTypeHandle); if (*ppv == IntPtr.Zero) { return(Interop.COM.E_NOINTERFACE); } else { return(Interop.COM.S_OK); } } }
public static int ReleaseComObject(object o) { if (o == null) { throw new ArgumentNullException("o"); } return(McgMarshal.Release(o as __ComObject)); }
public static bool IsComObject(object o) { if (o == null) { throw new ArgumentNullException(nameof(o)); } return(McgMarshal.IsComObject(o)); }
public static bool IsComObject(object o) { if (o == null) { throw new ArgumentNullException("o"); } return(McgMarshal.IsCOMObject(o.GetType())); }
internal static Exception AttachRestrictedErrorInfo(Exception e) { // If there is no exception, then the restricted error info doesn't apply to it if (e != null) { System.IntPtr pRestrictedErrorInfo = IntPtr.Zero; try { // Get the restricted error info for this thread and see if it may correlate to the current // exception object. Note that in general the thread's IRestrictedErrorInfo is not meant for // exceptions that are marshaled Windows.Foundation.HResults and instead are intended for // HRESULT ABI return values. However, in many cases async APIs will set the thread's restricted // error info as a convention in order to provide extended debugging information for the ErrorCode // property. if (TryGetRestrictedErrorInfo(out pRestrictedErrorInfo)) { string description; string restrictedDescription; string capabilitySid; int restrictedErrorInfoHResult; if (RestrictedErrorInfoHelper.GetErrorDetails( pRestrictedErrorInfo, out description, out restrictedErrorInfoHResult, out restrictedDescription, out capabilitySid) && (e.HResult == restrictedErrorInfoHResult)) { // Since this is a special case where by convention there may be a correlation, there is not a // guarantee that the restricted error info does belong to the async error code. In order to // reduce the risk that we associate incorrect information with the exception object, we need // to apply a heuristic where we attempt to match the current exception's HRESULT with the // HRESULT the IRestrictedErrorInfo belongs to. If it is a match we will assume association // for the IAsyncInfo case. string errorReference; RestrictedErrorInfoHelper.GetReference(pRestrictedErrorInfo, out errorReference); object restrictedErrorInfo = McgMarshal.ComInterfaceToObject(pRestrictedErrorInfo, InternalTypes.IRestrictedErrorInfo); InteropExtensions.AddExceptionDataForRestrictedErrorInfo( e, restrictedDescription, errorReference, capabilitySid, restrictedErrorInfo); } } } catch (Exception) { // If we can't get the restricted error info, then proceed as if it isn't associated with this // error. } finally { McgMarshal.ComSafeRelease(pRestrictedErrorInfo); } } return(e); }
/// <summary> /// Returns whether the IUnknown* is a free-threaded COM object /// </summary> /// <param name="pUnknown"></param> internal static unsafe bool IsFreeThreaded(IntPtr pUnknown) { // // Does it support IAgileObject? // IntPtr pAgileObject = McgMarshal.ComQueryInterfaceNoThrow(pUnknown, ref Interop.COM.IID_IAgileObject); if (pAgileObject != default(IntPtr)) { // Anything that implements IAgileObject is considered to be free-threaded // NOTE: This doesn't necessarily mean that the object is free-threaded - it only means // we BELIEVE it is free-threaded McgMarshal.ComRelease_StdCall(pAgileObject); return(true); } IntPtr pMarshal = McgMarshal.ComQueryInterfaceNoThrow(pUnknown, ref Interop.COM.IID_IMarshal); if (pMarshal == default(IntPtr)) { return(false); } try { // // Check the un-marshaler // Interop.COM.__IMarshal *pIMarshalNativePtr = (Interop.COM.__IMarshal *)(void *) pMarshal; fixed(Guid *pGuid = &Interop.COM.IID_IUnknown) { Guid clsid; int hr = CalliIntrinsics.StdCall__int( pIMarshalNativePtr->vtbl->pfnGetUnmarshalClass, new IntPtr(pIMarshalNativePtr), pGuid, default(IntPtr), (uint)Interop.COM.MSHCTX.MSHCTX_INPROC, default(IntPtr), (uint)Interop.COM.MSHLFLAGS.MSHLFLAGS_NORMAL, &clsid); if (hr >= 0 && InteropExtensions.GuidEquals(ref clsid, ref Interop.COM.CLSID_InProcFreeMarshaler)) { // The un-marshaller is indeed the unmarshaler for the FTM so this object // is free threaded. return(true); } } return(false); } finally { McgMarshal.ComRelease_StdCall(pMarshal); } }
#pragma warning restore 649, 169 /// <summary> /// This method gets the mapping hr for the exception. and also does the right thing to propogate the hr correctly to the native layer. /// /// We check if the exception is a pure managed exception or an exception created from an hr that entered the system from native. /// a. If it is a pure managed exception we create an IUnknown ptr from the exception and RoOriginateLanguageException on it. /// This helps us to preserve our managed exception and throw the same exception in case this exception roundtrips and hence preserve the call stack. /// Since the API RoOriginateLanguageException is available only on windows blue, we can't do the same in win8. In desktop CLR we use the non-modern SDK API /// GetErroInfo\SetErrorInfo combination to preserve managed exception but unfortunately we can't do this in .NET Native and hence we only our able to preserve the exception message and /// type and end up getting a rough stacktrace PS - Even this behavior in win8 is possible only in debug mode as RoSetErrorReportingFlags is set to UseSetErrorInfo only in debug mode. /// /// b. In case the exception is created due to an hr that entered managed world via native call, we will have restrictederrorInfo associated with it. In this case /// we do not RoOriginateLanguageException\RoOriginateError and rather preserve the exception stack trace by simply calling the SetRestrictedErrorInfo. /// /// c. PS - Due to the use of modern SDK we have no way to round trip exceptions in classicCOM scenarios any more. /// This is because we can't use SetErrorInfo\GetErrorInfo APIs at all. Unfortunately we have no workaround for this even in windowsBlue! /// With the use of IRestrictedErrorInfo has some disadvantages as we lose other info available with IErrorInfo in terms of HelpFile etc. /// /// d. This class puts all the logic in try, catch block to ensure that none of the exception helpers. /// throw exception themselves. /// </summary> /// <param name="ex"></param> /// <param name="isWinRTScenario"></param> /// <returns></returns> internal static int GetHRForExceptionWithErrorPropogationNoThrow(Exception ex, bool isWinRTScenario) { int hr = ex.HResult; if (hr == Interop.COM.COR_E_OBJECTDISPOSED && isWinRTScenario) { // Since ObjectDisposedException is projected to RO_E_CLOSED in WINRT we make sure to use the correct hr while updating the CRuntimeError object of Windows. hr = Interop.COM.RO_E_CLOSED; } try { // Check whether the exception has an associated RestrictedErrorInfo associated with it. if (isWinRTScenario) { IntPtr pRestrictedErrorInfo; object restrictedErrorInfo; if (InteropExtensions.TryGetRestrictedErrorObject(ex, out restrictedErrorInfo) && restrictedErrorInfo != null) { // We have the restricted errorInfo associated with this object and hence this exception was created by an hr entering managed through native. pRestrictedErrorInfo = McgMarshal.ObjectToComInterface(restrictedErrorInfo, InternalTypes.IRestrictedErrorInfo); if (pRestrictedErrorInfo != IntPtr.Zero) { // We simply call SetRestrictedErrorInfo since we do not want to originate the exception again. ExternalInterop.SetRestrictedErrorInfo(pRestrictedErrorInfo); McgMarshal.ComSafeRelease(pRestrictedErrorInfo); } } else { // we are in windows blue and hence we can preserve our exception so that we can reuse this exception in case it comes back and provide richer exception support. OriginateLanguageException(ex); } } else { // We are either pre WinBlue or in classicCOM scenario and hence we can only RoOriginateError at this point. // Desktop CLR uses SetErrorInfo and preserves the exception object which helps us give the same support as winBlue. // Since .NET Native can only use modern SDK we have a compatibility break here by only preserving the restrictederrorMsg and exception type but the stack trace will be incorrect. // Also RoOriginateError works only under the debugger since RoSetErrorReportingFlags is set to RO_ERROR_REPORTING_USESETERRORINFO. // If we are not under the debugger we can't set this API since it is not part of the modernSDK and hence this will not work // and will result in different behavior than the desktop. HSTRING errorMsg = McgMarshal.StringToHString(ex.Message); ExternalInterop.RoOriginateError(ex.HResult, errorMsg); ExternalInterop.WindowsDeleteString(errorMsg.handle.ToPointer()); } } catch (Exception) { // We can't throw an exception here and hence simply swallow it. } return(hr); }
//==================================================================== // Checks if "t" is MCG generated , if not fallback to public API //==================================================================== public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t) { Delegate dlg = McgMarshal.GetPInvokeDelegateForStub(ptr, t.TypeHandle); #if CORECLR if (dlg == null) // fall back to public marshal API { return(Marshal.GetDelegateForFunctionPointer(ptr, t)); } #endif return(dlg); }
//==================================================================== // return an Object for IUnknown //==================================================================== public static Object GetObjectForIUnknown(IntPtr /* IUnknown* */ pUnk) { object obj = McgMarshal.ComInterfaceToObject(pUnk, InternalTypes.IUnknown); #if CORECLR if (obj == null) { return(Marshal.GetObjectForIUnknown(pUnk)); } #endif return(obj); }
/// <summary> /// Release a IStream that has marshalled data in it /// </summary> internal static void SafeReleaseStream(IntPtr pStream) { Debug.Assert(pStream != default(IntPtr)); #if ENABLE_WINRT // Release marshalled data and ignore any error ExternalInterop.CoReleaseMarshalData(pStream); McgMarshal.ComRelease(pStream); #else throw new PlatformNotSupportedException("SafeReleaseStream"); #endif }
public static int QueryInterface(IntPtr pUnk, ref Guid iid, out IntPtr ppv) { int hr = 0; ppv = McgMarshal.ComQueryInterfaceNoThrow(pUnk, ref iid, out hr); #if CORECLR if (ppv == default(IntPtr)) { return(Marshal.QueryInterface(pUnk, ref iid, out ppv)); } #endif return(hr); }
internal static bool GetErrorDetails(System.IntPtr pRestrictedErrorInfo, out string errMsg, out int hr, out string resErrMsg, out string errCapSid) { Debug.Assert(pRestrictedErrorInfo != IntPtr.Zero); IntPtr pErrDes, pResErrDes, pErrCapSid; pErrDes = pResErrDes = pErrCapSid = IntPtr.Zero; int result; try { // Get the errorDetails associated with the restrictedErrorInfo. __com_IRestrictedErrorInfo *pComRestrictedErrorInfo = (__com_IRestrictedErrorInfo *)pRestrictedErrorInfo; result = CalliIntrinsics.StdCall__int( pComRestrictedErrorInfo->pVtable->pfnGetErrorDetails, pRestrictedErrorInfo, out pErrDes, out hr, out pResErrDes, out pErrCapSid); if (result >= 0) { // RestrictedErrorInfo details can be used since the pRestrictedErrorInfo has the same hr value as the hr returned by the native code. errMsg = Interop.COM.ConvertBSTRToString(pErrDes); resErrMsg = Interop.COM.ConvertBSTRToString(pResErrDes); errCapSid = Interop.COM.ConvertBSTRToString(pErrCapSid); } else { errMsg = resErrMsg = errCapSid = null; hr = 0; } } finally { if (pErrDes != IntPtr.Zero) { McgMarshal.SysFreeString(pErrDes); } if (pResErrDes != IntPtr.Zero) { McgMarshal.SysFreeString(pResErrDes); } if (pErrCapSid != IntPtr.Zero) { McgMarshal.SysFreeString(pErrCapSid); } } return(result >= 0); }
#pragma warning restore 649, 169 /// <summary> /// This method gets called every time the WeakReference or WeakReference'1 set the Target. /// We can have 4 possible combination here. /// a. Target is a GC object and it is either getting set for the first time or previous object is also GC object. /// In this case we do not need to do anything. /// /// b. Target is a GC object and previous target was __ComObject /// i. We remove the element from ConditionalWeakTable. /// ii. When the GC collects this ComWeakReference the finalizer will ensure that the native object is released. /// /// c. Target is a __ComObject and the previous target was null or GC object. /// We simply add the new target to the dictionary. /// /// d. Target is a __COmObject and the previous object was __COmObject. /// i. We first remove the element from the ConditionalWeakTable. /// ii. When the GC collects the previous ComWeakReference the finalizer will ensure that the native object is released. /// iii. We add the new ComWeakReference to the conditionalWeakTable. /// </summary> /// <param name="weakReference"></param> /// <param name="target"></param> public static unsafe void SetTarget(object weakReference, object target) { Contract.Assert(weakReference != null); // Check if this weakReference is already associated with a native target. ComWeakReference pOldComWeakReference; if (s_COMWeakReferenceTable.TryGetValue(weakReference, out pOldComWeakReference)) { // Remove the previous target. // We do not have to release the native ComWeakReference since it will be done as part of the finalizer. s_COMWeakReferenceTable.Remove(weakReference); } // Now check whether the current target is __ComObject. // However, we don't want to pass the QI to a managed object deriving from native object - we // would end up passing the QI to back the CCW and end up stack overflow __ComObject comObject = target as __ComObject; if (comObject != null && !comObject.ExtendsComObject) { // Get the IWeakReferenceSource for the given object IntPtr pWeakRefSource = McgMarshal.ObjectToComInterface(comObject, McgModuleManager.IWeakReferenceSource); if (pWeakRefSource != IntPtr.Zero) { IntPtr pWeakRef = IntPtr.Zero; try { // Now that we have the IWeakReferenceSource , we need to call the GetWeakReference method to get the corresponding IWeakReference __com_IWeakReferenceSource *pComWeakRefSource = (__com_IWeakReferenceSource *)pWeakRefSource; int result = CalliIntrinsics.StdCall <int>( pComWeakRefSource->pVtable->pfnGetWeakReference, pWeakRefSource, out pWeakRef); if (result >= 0 && pWeakRef != IntPtr.Zero) { // Since we have already checked s_COMWeakReferenceTable for the weak reference, we can simply add the entry w/o checking. // PS - We do not release the pWeakRef as it should be alive until the ComWeakReference is alive. s_COMWeakReferenceTable.Add(weakReference, new ComWeakReference(ref pWeakRef)); } } finally { McgMarshal.ComSafeRelease(pWeakRef); McgMarshal.ComRelease(pWeakRefSource); } } } }
public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type t) { if (o == null) { throw new ArgumentNullException("o"); } if (t == null) { throw new ArgumentNullException("type"); } return(McgMarshal.ObjectToComInterface(o, t.TypeHandle)); }
/// <summary> /// Returns the requested interface pointer specified by itfType from the CCWActivationFactory /// object instance. Typically the requested interface is the /// System.Runtime.InteropServices.WindowsRuntime.IActivationFactory interface. /// </summary> public unsafe int GetCCWActivationFactory(HSTRING activatableClassId, RuntimeTypeHandle itfType, IntPtr *factoryOut) { try { string classId = McgMarshal.HStringToString(activatableClassId); if (classId == null) { return(Interop.COM.E_INVALIDARG); } RuntimeTypeHandle factoryTypeHandle = default(RuntimeTypeHandle); if (m_ccwFactoriesNameMap != null) { int slot = m_ccwFactoriesNameMap.FindString(classId); if (slot >= 0) { factoryTypeHandle = m_ccwFactories[slot].FactoryType; } } if (factoryTypeHandle.IsNull()) { return(Interop.COM.E_NOINTERFACE); } object factory = InteropExtensions.RuntimeNewObject(factoryTypeHandle); *factoryOut = McgMarshal.ObjectToComInterface( factory, itfType); } catch (Exception ex) { *factoryOut = default(IntPtr); return(McgMarshal.GetHRForExceptionWinRT(ex)); } return(Interop.COM.S_OK); }
internal static bool ReportUnhandledError(Exception e) { System.IntPtr pRestrictedErrorInfo = IntPtr.Zero; if (e != null) { try { #if ENABLE_WINRT // Only report to the WinRT global exception handler in modern apps WinRTInteropCallbacks callbacks = WinRTInterop.Callbacks; if (callbacks == null || !callbacks.IsAppxModel()) { return(false); } // Get the IUnknown for the current exception and originate it as a langauge error in order to have // Windows generate an IRestrictedErrorInfo corresponding to the exception object. We can then // notify the global error handler that this IRestrictedErrorInfo instance represents an exception that // went unhandled in managed code. if (OriginateLanguageException(e) && TryGetRestrictedErrorInfo(out pRestrictedErrorInfo)) { return(ExternalInterop.RoReportUnhandledError(pRestrictedErrorInfo) >= 0); } #else return(false); #endif // ENABLE_WINRT } catch (Exception) { // We can't give an exception in this code, so we simply swallow the exception here. } finally { McgMarshal.ComSafeRelease(pRestrictedErrorInfo); } } // If we have got here, then some step of the pInvoke failed, which means the GEH was not invoked return(false); }
public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T) { if (o == null) { throw new ArgumentNullException(nameof(o)); } if (T == null) { throw new ArgumentNullException(nameof(T)); } IntPtr ptr = McgMarshal.ObjectToComInterface(o, T.TypeHandle); #if CORECLR if (ptr == default(IntPtr)) { return(Marshal.GetComInterfaceForObject(o, T)); } #endif return(ptr); }
public unsafe int DllGetClassObjectImpl(Guid rclsid, Guid riid, IntPtr *ppv) { if (riid != s_IID_IClassFactory) { // Make sure we generate a CCW for IClassFactory // IntPtr dummy = Marshal.GetComInterfaceForObject(new ClassFactory(null, typeof(IClassFactory).TypeHandle), typeof(IClassFactory)); // Marshal.Release(dummy); return(Interop.COM.E_NOINTERFACE); } // TODO: build a index similar as McgModule.m_guidMap for (int i = 0; i < this.m_ccwTemplateData.Length; i++) { if (this.m_ccwTemplateData[i].Clsid == rclsid) { ClassFactory classFactory = new ClassFactory(this, this.m_ccwTemplateData[i].ClassType); * ppv = McgMarshal.ObjectToComInterface(classFactory, typeof(IClassFactory).TypeHandle); return(Interop.COM.S_OK); } } return(Interop.COM.CLASS_E_CLASSNOTAVAILABLE); }
/// <summary> /// Returns the existing RCW or create a new RCW from the COM interface pointer /// NOTE: Don't use this overload if you already have the identity IUnknown /// </summary> /// <param name="expectedContext"> /// The current context of this thread. If it is passed and is not Default, we'll check whether the /// returned RCW from cache matches this expected context. If it is not a match (from a different /// context, and is not free threaded), we'll go ahead ignoring the cached entry, and create a new /// RCW instead - which will always end up in the current context /// We'll skip the check if current == ContextCookie.Default. /// </param> internal static object ComInterfaceToComObject( IntPtr pComItf, RuntimeTypeHandle interfaceType, RuntimeTypeHandle classTypeInSigature, ContextCookie expectedContext, CreateComObjectFlags flags ) { Debug.Assert(expectedContext.IsDefault || expectedContext.IsCurrent); // // Get identity IUnknown for lookup // IntPtr pComIdentityIUnknown = McgMarshal.ComQueryInterfaceNoThrow(pComItf, ref Interop.COM.IID_IUnknown); if (pComIdentityIUnknown == default(IntPtr)) { throw new InvalidCastException(); } try { object obj = ComInterfaceToComObjectInternal( pComItf, pComIdentityIUnknown, interfaceType, classTypeInSigature, expectedContext, flags ); return(obj); } finally { McgMarshal.ComRelease(pComIdentityIUnknown); } }
public static int Release(IntPtr pUnk) { return(McgMarshal.ComRelease(pUnk)); }
public static int AddRef(IntPtr pUnk) { return(McgMarshal.ComAddRef(pUnk)); }
public static int FinalReleaseComObject(object o) { return(McgMarshal.FinalReleaseComObject(o)); }