Beispiel #1
0
        /// <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
        }
Beispiel #2
0
        /// <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
        }
Beispiel #3
0
            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);
                    }
                }
            }
Beispiel #4
0
        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);
            }
        }
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");
            }

            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));
        }
Beispiel #6
0
            /// <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);
            }
Beispiel #7
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 #8
0
        /// <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);
                }
            }
        }
Beispiel #10
0
 public static int ReleaseComObject(object o)
 {
     if (o == null)
     {
         throw new ArgumentNullException("o");
     }
     return(McgMarshal.Release(o as __ComObject));
 }
Beispiel #11
0
 public static bool IsComObject(object o)
 {
     if (o == null)
     {
         throw new ArgumentNullException(nameof(o));
     }
     return(McgMarshal.IsComObject(o));
 }
Beispiel #12
0
 public static bool IsComObject(object o)
 {
     if (o == null)
     {
         throw new ArgumentNullException("o");
     }
     return(McgMarshal.IsCOMObject(o.GetType()));
 }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        /// <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);
            }
        }
Beispiel #15
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 #16
0
        //====================================================================
        // 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);
        }
Beispiel #17
0
        //====================================================================
        // 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);
        }
Beispiel #18
0
        /// <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
        }
Beispiel #19
0
        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);
        }
Beispiel #20
0
            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);
            }
Beispiel #21
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 #22
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 #23
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 #24
0
        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);
        }
Beispiel #25
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 #26
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 #27
0
        /// <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);
            }
        }
Beispiel #28
0
 public static int Release(IntPtr pUnk)
 {
     return(McgMarshal.ComRelease(pUnk));
 }
Beispiel #29
0
 public static int AddRef(IntPtr pUnk)
 {
     return(McgMarshal.ComAddRef(pUnk));
 }
Beispiel #30
0
 public static int FinalReleaseComObject(object o)
 {
     return(McgMarshal.FinalReleaseComObject(o));
 }