Пример #1
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);
            }
        }