Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        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));
        }
        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);
                }
            }
        }
Beispiel #4
0
#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);
        }
Beispiel #5
0
        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));
        }
Beispiel #6
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);
                    }
                }
            }
        }
Beispiel #7
0
        /// <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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
 public static IntPtr /* IUnknown* */ GetIUnknownForObject(Object o)
 {
     return(McgMarshal.ObjectToComInterface(o, InternalTypes.IUnknown));
 }
Beispiel #11
0
 public static IntPtr /* IUnknown* */ GetIUnknownForObject(Object o)
 {
     return(McgMarshal.ObjectToComInterface(o, McgModuleManager.IUnknown));
 }