/// <summary>
        /// Look for typeinfo using IDispatch.GetTypeInfo
        /// </summary>
        /// <param name="dispatch"></param>
        /// <param name="throwIfMissingExpectedTypeInfo">
        /// Some COM objects just dont expose typeinfo. In these cases, this method will return null.
        /// Some COM objects do intend to expose typeinfo, but may not be able to do so if the type-library is not properly 
        /// registered. This will be considered as acceptable or as an error condition depending on throwIfMissingExpectedTypeInfo</param>
        /// <returns></returns>
        internal static ComTypes.ITypeInfo GetITypeInfoFromIDispatch(IDispatch dispatch, bool throwIfMissingExpectedTypeInfo) {
            uint typeCount;
            int hresult = dispatch.TryGetTypeInfoCount(out typeCount);
            Marshal.ThrowExceptionForHR(hresult);
            Debug.Assert(typeCount <= 1);
            if (typeCount == 0) {
                return null;
            }

            IntPtr typeInfoPtr = IntPtr.Zero;

            hresult = dispatch.TryGetTypeInfo(0, 0, out typeInfoPtr);
            if (!ComHresults.IsSuccess(hresult)) {
                CheckIfMissingTypeInfoIsExpected(hresult, throwIfMissingExpectedTypeInfo);
                return null;
            }
            if (typeInfoPtr == IntPtr.Zero) { // be defensive against components that return IntPtr.Zero
                if (throwIfMissingExpectedTypeInfo) {
                    Marshal.ThrowExceptionForHR(ComHresults.E_FAIL);
                }
                return null;
            }

            ComTypes.ITypeInfo typeInfo = null;
            try {
                typeInfo = Marshal.GetObjectForIUnknown(typeInfoPtr) as ComTypes.ITypeInfo;
            } finally {
                Marshal.Release(typeInfoPtr);
            }

            return typeInfo;
        }
Beispiel #2
0
        /// <summary>
        /// Look for typeinfo using IDispatch.GetTypeInfo.
        /// </summary>
        /// <param name="dispatch">IDispatch object</param>
        /// <remarks>
        /// Some COM objects just dont expose typeinfo. In these cases, this method will return null.
        /// Some COM objects do intend to expose typeinfo, but may not be able to do so if the type-library is not properly
        /// registered. This will be considered as acceptable or as an error condition depending on throwIfMissingExpectedTypeInfo
        /// </remarks>
        /// <returns>Type info</returns>
        internal static ComTypes.ITypeInfo GetITypeInfoFromIDispatch(IDispatch dispatch)
        {
            int hresult = dispatch.TryGetTypeInfoCount(out uint typeCount);

            if (hresult == ComHresults.E_NOTIMPL || hresult == ComHresults.E_NOINTERFACE)
            {
                // Allow the dynamic binding to continue using the original binder.
                return(null);
            }
            else
            {
                Marshal.ThrowExceptionForHR(hresult);
            }

            Debug.Assert(typeCount <= 1);
            if (typeCount == 0)
            {
                return(null);
            }

            IntPtr typeInfoPtr;

            hresult = dispatch.TryGetTypeInfo(0, 0, out typeInfoPtr);
            if (!ComHresults.IsSuccess(hresult))
            {
                // Word.Basic always returns this because of an incorrect implementation of IDispatch.GetTypeInfo
                // Any implementation that returns E_NOINTERFACE is likely to do so in all environments
                if (hresult == ComHresults.E_NOINTERFACE)
                {
                    return(null);
                }

                // This assert is potentially over-restrictive since COM components can behave in quite unexpected ways.
                // However, asserting the common expected cases ensures that we find out about the unexpected scenarios, and
                // can investigate the scenarios to ensure that there is no bug in our own code.
                Debug.Assert(hresult == ComHresults.TYPE_E_LIBNOTREGISTERED);

                Marshal.ThrowExceptionForHR(hresult);
            }

            if (typeInfoPtr == IntPtr.Zero)
            {
                Marshal.ThrowExceptionForHR(ComHresults.E_FAIL);
            }

            ComTypes.ITypeInfo typeInfo = null;
            try
            {
                typeInfo = Marshal.GetObjectForIUnknown(typeInfoPtr) as ComTypes.ITypeInfo;
            }
            finally
            {
                Marshal.Release(typeInfoPtr);
            }

            return(typeInfo);
        }
Beispiel #3
0
        /// <summary>
        /// Look for type info using IDispatch.GetTypeInfo
        /// </summary>
        /// <param name="dispatch">IDispatch object</param>
        /// <remarks>
        /// Some COM objects just don't expose type info. In these cases, this method will return null.
        /// Some COM objects do intend to expose type info, but may not be able to do so if the type library
        /// is not properly registered. This will be considered an error.
        /// </remarks>
        /// <returns>Type info</returns>
        internal static ComTypes.ITypeInfo GetITypeInfoFromIDispatch(IDispatch dispatch)
        {
            int hresult = dispatch.TryGetTypeInfoCount(out uint typeCount);

            if (typeCount == 0)
            {
                // COM objects should return a type count of 0 to indicate that type info is not exposed.
                // Some COM objects may return a non-success HRESULT when type info is not supported, so
                // we only check the count and not the HRESULT in this case.
                return(null);
            }

            Marshal.ThrowExceptionForHR(hresult);
            Debug.Assert(typeCount == 1);

            IntPtr typeInfoPtr;

            hresult = dispatch.TryGetTypeInfo(0, 0, out typeInfoPtr);
            if (!ComHresults.IsSuccess(hresult))
            {
                // Word.Basic always returns this because of an incorrect implementation of IDispatch.GetTypeInfo
                // Any implementation that returns E_NOINTERFACE is likely to do so in all environments
                if (hresult == ComHresults.E_NOINTERFACE)
                {
                    return(null);
                }

                // This assert is potentially over-restrictive since COM components can behave in quite unexpected ways.
                // However, asserting the common expected cases ensures that we find out about the unexpected scenarios, and
                // can investigate the scenarios to ensure that there is no bug in our own code.
                Debug.Assert(hresult == ComHresults.TYPE_E_LIBNOTREGISTERED);

                Marshal.ThrowExceptionForHR(hresult);
            }

            if (typeInfoPtr == IntPtr.Zero)
            {
                Marshal.ThrowExceptionForHR(ComHresults.E_FAIL);
            }

            ComTypes.ITypeInfo typeInfo = null;
            try
            {
                typeInfo = Marshal.GetObjectForIUnknown(typeInfoPtr) as ComTypes.ITypeInfo;
            }
            finally
            {
                Marshal.Release(typeInfoPtr);
            }

            return(typeInfo);
        }
Beispiel #4
0
        /// <summary>
        /// Look for typeinfo using IDispatch.GetTypeInfo.
        /// </summary>
        /// <param name="dispatch"></param>
        /// <param name="throwIfMissingExpectedTypeInfo">
        /// Some COM objects just dont expose typeinfo. In these cases, this method will return null.
        /// Some COM objects do intend to expose typeinfo, but may not be able to do so if the type-library is not properly
        /// registered. This will be considered as acceptable or as an error condition depending on throwIfMissingExpectedTypeInfo</param>
        /// <returns></returns>
        internal static ComTypes.ITypeInfo GetITypeInfoFromIDispatch(IDispatch dispatch, bool throwIfMissingExpectedTypeInfo)
        {
            uint typeCount;
            int  hresult = dispatch.TryGetTypeInfoCount(out typeCount);

            if ((hresult == ComHresults.E_NOTIMPL) || (hresult == ComHresults.E_NOINTERFACE))
            {
                return(null);
            }
            else
            {
                Marshal.ThrowExceptionForHR(hresult);
            }

            Debug.Assert(typeCount <= 1);
            if (typeCount == 0)
            {
                return(null);
            }

            IntPtr typeInfoPtr = IntPtr.Zero;

            hresult = dispatch.TryGetTypeInfo(0, 0, out typeInfoPtr);
            if (!Utils.Succeeded(hresult))
            {
                CheckIfMissingTypeInfoIsExpected(hresult, throwIfMissingExpectedTypeInfo);
                return(null);
            }

            if (typeInfoPtr == IntPtr.Zero)
            { // be defensive against components that return IntPtr.Zero
                if (throwIfMissingExpectedTypeInfo)
                {
                    Marshal.ThrowExceptionForHR(ComHresults.E_FAIL);
                }

                return(null);
            }

            ComTypes.ITypeInfo typeInfo = null;
            try
            {
                typeInfo = Marshal.GetObjectForIUnknown(typeInfoPtr) as ComTypes.ITypeInfo;
            }
            finally
            {
                Marshal.Release(typeInfoPtr);
            }

            return(typeInfo);
        }