Пример #1
0
        internal static unsafe IntPtr ObjectToComInterfaceInternal(Object obj, RuntimeTypeHandle typeHnd)
        {
            if (obj == null)
            {
                return(default(IntPtr));
            }

#if ENABLE_WINRT
            //
            // Try boxing if this is a WinRT object
            //
            if (typeHnd.Equals(InternalTypes.IInspectable))
            {
                object unboxed = McgMarshal.BoxIfBoxable(obj);

                //
                // Marshal ReferenceImpl<T> to WinRT as IInspectable
                //
                if (unboxed != null)
                {
                    obj = unboxed;
                }
                else
                {
                    //
                    // Anything that can be casted to object[] will be boxed as object[]
                    //
                    object[] objArray = obj as object[];
                    if (objArray != null)
                    {
                        unboxed = McgMarshal.BoxIfBoxable(obj, typeof(object[]).TypeHandle);
                        if (unboxed != null)
                        {
                            obj = unboxed;
                        }
                    }
                }
            }
#endif //ENABLE_WINRT

            //
            // If this is a RCW, and the RCW is not a base class (managed class deriving from RCW class),
            // QI on the RCW
            //
            __ComObject comObject = obj as __ComObject;

            if (comObject != null && !comObject.ExtendsComObject)
            {
                IntPtr pComPtr = comObject.QueryInterface_NoAddRef_Internal(typeHnd, /* cacheOnly= */ false, /* throwOnQueryInterfaceFailure= */ false);
                if (pComPtr == default(IntPtr))
                {
                    return(default(IntPtr));
                }

                McgMarshal.ComAddRef(pComPtr);
                GC.KeepAlive(comObject); // make sure we don't collect the object before adding a refcount.

                return(pComPtr);
            }

            //
            // Otherwise, go down the CCW code path
            //
            return(ManagedObjectToComInterface(obj, typeHnd));
        }
Пример #2
0
 public static int AddRef(IntPtr pUnk)
 {
     return(McgMarshal.ComAddRef(pUnk));
 }
Пример #3
0
        /// <summary>
        /// Returns the existing RCW or create a new RCW from the COM interface pointer
        /// NOTE: This does unboxing unless CreateComObjectFlags.SkipTypeResolutionAndUnboxing is specified
        /// </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 ComInterfaceToComObjectInternal(
            IntPtr pComItf,
            IntPtr pComIdentityIUnknown,
            RuntimeTypeHandle interfaceType,
            RuntimeTypeHandle classTypeInSignature,
            ContextCookie expectedContext,
            CreateComObjectFlags flags
            )
        {
            string className;
            object obj = ComInterfaceToComObjectInternal_NoCache(
                pComItf,
                pComIdentityIUnknown,
                interfaceType,
                classTypeInSignature,
                expectedContext,
                flags,
                out className
                );

            //
            // The assumption here is that if the classInfoInSignature is null and interfaceTypeInfo
            // is either IUnknow and IInspectable we need to try unboxing.
            //
            bool doUnboxingCheck =
                (flags & CreateComObjectFlags.SkipTypeResolutionAndUnboxing) == 0 &&
                obj != null &&
                classTypeInSignature.IsNull() &&
                (interfaceType.Equals(InternalTypes.IUnknown) ||
                 interfaceType.IsIInspectable());

            if (doUnboxingCheck)
            {
                //
                // Try unboxing
                // Even though this might just be a IUnknown * from the signature, we still attempt to unbox
                // if it implements IInspectable
                //
                // @TODO - We might need to optimize this by pre-checking the names to see if they
                // potentially represents a boxed type, but for now let's keep it simple and I also don't
                // want to replicate the knowledge here
                // @TODO2- We probably should skip the creating the COM object in the first place.
                //
                // NOTE: the RCW here could be a cached one (for a brief time if GC doesn't kick in. as there
                // is nothing to hold the RCW alive for IReference<T> RCWs), so this could save us a RCW
                // creation cost potentially. Desktop CLR doesn't do this. But we also paying for unnecessary
                // cache management cost, and it is difficult to say which way is better without proper
                // measuring
                //
                object unboxedObj = McgMarshal.UnboxIfBoxed(obj, className);
                if (unboxedObj != null)
                {
                    return(unboxedObj);
                }
            }

            //
            // In order for variance to work, we save the incoming interface pointer as specified in the
            // signature into the cache, so that we know this RCW does support this interface and variance
            // can take advantage of that later
            // NOTE: In some cases, native might pass a WinRT object as a 'compatible' interface, for example,
            // pass IVector<IFoo> as IVector<Object> because they are 'compatible', but QI for IVector<object>
            // won't succeed. In this case, we'll just believe it implements IVector<Object> as in the
            // signature while the underlying interface pointer is actually IVector<IFoo>
            //
            __ComObject comObject = obj as __ComObject;

            if (comObject != null)
            {
                McgMarshal.ComAddRef(pComItf);

                try
                {
                    comObject.InsertIntoCache(interfaceType, ContextCookie.Current, ref pComItf, true);
                }
                finally
                {
                    //
                    // Only release when a exception is thrown or we didn't 'swallow' the ref count by
                    // inserting it into the cache
                    //
                    McgMarshal.ComSafeRelease(pComItf);
                }
            }

            return(obj);
        }