示例#1
0
        public unsafe static int QueryInterface(IntPtr pUnk, ref Guid iid, out IntPtr ppv)
        {
            if (pUnk == IntPtr.Zero)
            {
                throw new ArgumentNullException(nameof(pUnk));
            }

            IntPtr pComIUnk;
            int    hr;

            fixed(Guid *unsafe_iid = &iid)
            {
                hr = CalliIntrinsics.StdCall__QueryInterface(((__com_IUnknown *)(void *)pUnk)->pVtable->
                                                             pfnQueryInterface,
                                                             pUnk,
                                                             new IntPtr(unsafe_iid),
                                                             new IntPtr(&pComIUnk));
            }

            if (hr != 0)
            {
                ppv = default(IntPtr);
            }
            else
            {
                ppv = pComIUnk;
            }

            return(hr);
        }
示例#2
0
        private static __ComObject CreateComObjectInternal(RuntimeTypeHandle classType, IntPtr pComItf)
        {
            Debug.Assert(!classType.IsNull());

            if (classType.Equals(McgModule.s_DependencyReductionTypeRemovedTypeHandle))
            {
                // We should filter out the strongly typed RCW in TryGetClassInfoFromName step
#if !RHTESTCL
                Environment.FailFast(McgTypeHelpers.GetDiagnosticMessageForMissingType(classType));
#else
                Environment.FailFast("We should never see strongly typed RCW discarded here");
#endif
            }

            //Note that this doesn't run the constructor in RH but probably do in your reflection based implementation.
            //If this were a real RCW, you would actually 'new' the RCW which is wrong. Fortunately in CoreCLR we don't have
            //this scenario so we are OK, but we should figure out a way to fix this by having a runtime API.
            object newClass = InteropExtensions.RuntimeNewObject(classType);

            Debug.Assert(newClass is __ComObject);

            __ComObject newObj = InteropExtensions.UncheckedCast <__ComObject>(newClass);

            IntPtr pfnCtor = AddrOfIntrinsics.AddrOf <AddrOfIntrinsics.AddrOfAttachingCtor>(__ComObject.AttachingCtor);
            CalliIntrinsics.Call <int>(pfnCtor, newObj, pComItf, classType);

            return(newObj);
        }
示例#3
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);
            }
示例#4
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)
                    {
                        ExternalInterop.SysFreeString(pReference);
                    }
                }
            }
示例#5
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
        }
示例#6
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);
            }
        }
示例#7
0
        public unsafe static int Release(IntPtr pUnk)
        {
            if (pUnk == IntPtr.Zero)
            {
                throw new ArgumentNullException(nameof(pUnk));
            }

            return(CalliIntrinsics.StdCall__Release(((__com_IUnknown *)(void *)pUnk)->pVtable->
                                                    pfnRelease, pUnk));
        }
示例#8
0
        /// <summary>
        /// Retrieve the corresponding P/invoke instance from the stub
        /// </summary>
        public static Delegate GetPInvokeDelegateForStub(IntPtr pStub, RuntimeTypeHandle delegateType)
        {
            if (pStub == IntPtr.Zero)
            {
                return(null);
            }
            //
            // First try to see if this is one of the thunks we've allocated when we marshal a managed
            // delegate to native code
            // s_thunkPoolHeap will be null if there isn't any managed delegate to native
            //
            IntPtr pContext;
            IntPtr pTarget;

            if (s_thunkPoolHeap != null && RuntimeAugments.TryGetThunkData(s_thunkPoolHeap, pStub, out pContext, out pTarget))
            {
                GCHandle handle;
                unsafe
                {
                    // Pull out Handle from context
                    handle = ((ThunkContextData *)pContext)->Handle;
                }
                Delegate target = InteropExtensions.UncheckedCast <Delegate>(handle.Target);

                //
                // The delegate might already been garbage collected
                // User should use GC.KeepAlive or whatever ways necessary to keep the delegate alive
                // until they are done with the native function pointer
                //
                if (target == null)
                {
                    Environment.FailFast(SR.Delegate_GarbageCollected);
                }

                return(target);
            }

            //
            // Otherwise, the stub must be a pure native function pointer
            // We need to create the delegate that points to the invoke method of a
            // NativeFunctionPointerWrapper derived class
            //
            McgPInvokeDelegateData pInvokeDelegateData;

            if (!RuntimeAugments.InteropCallbacks.TryGetMarshallerDataForDelegate(delegateType, out pInvokeDelegateData))
            {
                return(null);
            }
            return(CalliIntrinsics.Call <Delegate>(
                       pInvokeDelegateData.ForwardDelegateCreationStub,
                       pStub
                       ));
        }
示例#9
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)
                    {
                        ExternalInterop.SysFreeString(pErrDes);
                    }
                    if (pResErrDes != IntPtr.Zero)
                    {
                        ExternalInterop.SysFreeString(pResErrDes);
                    }
                    if (pErrCapSid != IntPtr.Zero)
                    {
                        ExternalInterop.SysFreeString(pErrCapSid);
                    }
                }

                return(result >= 0);
            }
示例#10
0
        /// <summary>
        /// Given a IStream*, seek to its beginning
        /// </summary>
        internal static unsafe bool SeekStreamToBeginning(IntPtr pStream)
        {
            Interop.COM.__IStream *pStreamNativePtr = (Interop.COM.__IStream *)(void *) pStream;
            UInt64 newPosition;

            int hr = CalliIntrinsics.StdCall__int(
                pStreamNativePtr->vtbl->pfnSeek,
                pStreamNativePtr,
                0UL,
                (uint)Interop.COM.STREAM_SEEK.STREAM_SEEK_SET,
                &newPosition);

            return(hr >= 0);
        }
示例#11
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);
                    }
                }
            }
        }
示例#12
0
        /// <summary>
        /// Given a IStream*, change its size
        /// </summary>
        internal static unsafe bool SetStreamSize(IntPtr pStream, ulong lSize)
        {
            Interop.COM.__IStream *pStreamNativePtr = (Interop.COM.__IStream *)(void *) pStream;
            UInt64 newPosition;

            int hr = CalliIntrinsics.StdCall__int(
                pStreamNativePtr->vtbl->pfnSetSize,
                pStreamNativePtr,
                lSize,
                (uint)Interop.COM.STREAM_SEEK.STREAM_SEEK_SET,
                &newPosition);

            return(hr >= 0);
        }
示例#13
0
        public static unsafe void DestroyStructure(IntPtr ptr, Type structuretype)
        {
            if (ptr == IntPtr.Zero)
            {
                throw new ArgumentNullException(nameof(ptr));
            }

            if (structuretype == null)
            {
                throw new ArgumentNullException(nameof(structuretype));
            }

            RuntimeTypeHandle structureTypeHandle = structuretype.TypeHandle;

            if (structureTypeHandle.IsGenericType() || structureTypeHandle.IsGenericTypeDefinition())
            {
                throw new ArgumentException(SR.Argument_NeedNonGenericType, "t");
            }

            if (structureTypeHandle.IsEnum() ||
                structureTypeHandle.IsInterface() ||
                InteropExtensions.AreTypesAssignable(typeof(Delegate).TypeHandle, structureTypeHandle))
            {
                throw new ArgumentException(SR.Format(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.LastResortToString));
            }

            if (structureTypeHandle.IsBlittable())
            {
                // ok to call with blittable structure, but no work to do in this case.
                return;
            }

            IntPtr destroyStructureStub = RuntimeAugments.InteropCallbacks.GetDestroyStructureStub(structureTypeHandle, out bool hasInvalidLayout);

            if (hasInvalidLayout)
            {
                throw new ArgumentException(SR.Format(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.LastResortToString));
            }
            // DestroyStructureStub == IntPtr.Zero means its fields don't need to be destroied
            if (destroyStructureStub != IntPtr.Zero)
            {
                CalliIntrinsics.Call <int>(
                    destroyStructureStub,
                    (void *)ptr                                     // unsafe (no need to adjust as it is always struct)
                    );
            }
        }
示例#14
0
        internal static unsafe void PtrToStructureImpl(IntPtr ptr, object structure)
        {
            RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle;

            // Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0
            int offset = structureTypeHandle.IsValueType() ? 1 : 0;

            IntPtr unmarshalStub;

            if (structureTypeHandle.IsBlittable())
            {
                if (!RuntimeAugments.InteropCallbacks.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub))
                {
                    unmarshalStub = IntPtr.Zero;
                }
            }
            else
            {
                unmarshalStub = RuntimeAugments.InteropCallbacks.GetStructUnmarshalStub(structureTypeHandle);
            }

            if (unmarshalStub != IntPtr.Zero)
            {
                InteropExtensions.PinObjectAndCall(structure,
                                                   unboxedStructPtr =>
                {
                    CalliIntrinsics.Call <int>(
                        unmarshalStub,
                        (void *)ptr,                                        // unsafe (no need to adjust as it is always struct)
                        ((void *)((IntPtr *)unboxedStructPtr + offset))     // safe (need to adjust offset as it could be class)
                        );
                });
            }
            else
            {
                int structSize = Marshal.SizeOf(structure);
                InteropExtensions.PinObjectAndCall(structure,
                                                   unboxedStructPtr =>
                {
                    InteropExtensions.Memcpy(
                        (IntPtr)((IntPtr *)unboxedStructPtr + offset),      // safe (need to adjust offset as it could be class)
                        ptr,                                                // unsafe (no need to adjust as it is always struct)
                        structSize
                        );
                });
            }
        }
示例#15
0
        internal static unsafe void PtrToStructureImpl(IntPtr ptr, object structure)
        {
            RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle;

            IntPtr unmarshalStub;

            if (structureTypeHandle.IsBlittable())
            {
                if (!RuntimeAugments.InteropCallbacks.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub))
                {
                    unmarshalStub = IntPtr.Zero;
                }
            }
            else
            {
                unmarshalStub = RuntimeAugments.InteropCallbacks.GetStructUnmarshalStub(structureTypeHandle);
            }

            if (unmarshalStub != IntPtr.Zero)
            {
                if (structureTypeHandle.IsValueType())
                {
                    CalliIntrinsics.Call(
                        unmarshalStub,
                        ref *(byte *)ptr,
                        ref structure.GetRawData());
                }
                else
                {
                    CalliIntrinsics.Call(
                        unmarshalStub,
                        ref *(byte *)ptr,
                        structure);
                }
            }
            else
            {
                nuint size = (nuint)RuntimeAugments.InteropCallbacks.GetStructUnsafeStructSize(structureTypeHandle);
                fixed(byte *pDest = &structure.GetRawData())
                {
                    Buffer.Memmove(pDest, (byte *)ptr, size);
                }
            }
        }
示例#16
0
        public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld)
        {
            if (structure == null)
            {
                throw new ArgumentNullException(nameof(structure));
            }

            if (ptr == IntPtr.Zero)
            {
                throw new ArgumentNullException(nameof(ptr));
            }

            if (fDeleteOld)
            {
                DestroyStructure(ptr, structure.GetType());
            }

            RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle;

            if (structureTypeHandle.IsGenericType() || structureTypeHandle.IsGenericTypeDefinition())
            {
                throw new ArgumentException(nameof(structure), SR.Argument_NeedNonGenericObject);
            }

            IntPtr marshalStub;

            if (structureTypeHandle.IsBlittable())
            {
                if (!RuntimeAugments.InteropCallbacks.TryGetStructMarshalStub(structureTypeHandle, out marshalStub))
                {
                    marshalStub = IntPtr.Zero;
                }
            }
            else
            {
                marshalStub = RuntimeAugments.InteropCallbacks.GetStructMarshalStub(structureTypeHandle);
            }

            if (marshalStub != IntPtr.Zero)
            {
                if (structureTypeHandle.IsValueType())
                {
                    CalliIntrinsics.Call(marshalStub,
                                         ref structure.GetRawData(),
                                         ref *(byte *)ptr);
                }
                else
                {
                    CalliIntrinsics.Call(marshalStub,
                                         structure,
                                         ref *(byte *)ptr);
                }
            }
            else
            {
                nuint size = (nuint)RuntimeAugments.InteropCallbacks.GetStructUnsafeStructSize(structureTypeHandle);
                fixed(byte *pSrc = &structure.GetRawData())
                {
                    Buffer.Memmove((byte *)ptr, pSrc, size);
                }
            }
        }
示例#17
0
        /// <summary>
        /// This method returns a new Exception object given the HR value.
        ///
        /// 1. We check whether we have our own LanguageException associated with this hr. If so we simply use it since it helps preserve the stacktrace, message and type.
        ///    This is done using GetLanguageException API on ILanguageExceptionErrorInfo from IRestrictedErrorInfo. Since ILanguageExceptionErrorInfo is available only on Windows Blue
        ///    we can only do this WindowsBlue and above. In desktop CLR we could use GetErroInfo and check whether we have our IErroInfo and retrieve our own exception.
        ///    For Win8 in .NET Native we simply create the exception using the RestrictedErrorInfo and hence only able to give the exception with restrictedErrorMsg.
        /// 2. In case we do not have the languageException we simply check RestrictedErrorInfo for errorMsg and create an exception using
        ///   <errorMsg>\r\n<restrictedErrorMsg>. This is done for only windows blue. To be backward compatible we only use errorMsg for creating exception in win8.
        /// 3. PS - This class puts all the logic in try, catch block to ensure that none of the exception helpers
        ///  throw exception themselves.
        /// </summary>
        /// <param name="hr"></param>
        /// <param name="isWinRTScenario"></param>
        internal static Exception GetExceptionForHRInternalNoThrow(int hr, bool isWinRTScenario, bool isClassicCOM)
        {
            Exception ex;
            IntPtr    pRestrictedErrorInfo = IntPtr.Zero;

            try
            {
                if (TryGetRestrictedErrorInfo(out pRestrictedErrorInfo))
                {
                    // This is to check whether we need to give post win8 behavior or not.
                    if (isWinRTScenario)
                    {
                        // Check whether the given IRestrictedErrorInfo object supports ILanguageExceptionErrorInfo
                        IntPtr pLanguageExceptionErrorInfo = McgMarshal.ComQueryInterfaceNoThrow(pRestrictedErrorInfo, ref Interop.COM.IID_ILanguageExceptionErrorInfo);
                        if (pLanguageExceptionErrorInfo != IntPtr.Zero)
                        {
                            // We have an LanguageExceptionErrorInfo.
                            IntPtr pUnk;
                            __com_ILanguageExceptionErrorInfo *pComLanguageExceptionErrorInfo = (__com_ILanguageExceptionErrorInfo *)pLanguageExceptionErrorInfo;
                            int result = CalliIntrinsics.StdCall <int>(pComLanguageExceptionErrorInfo->pVtable->pfnGetLanguageException, pLanguageExceptionErrorInfo, out pUnk);
                            McgMarshal.ComSafeRelease(pLanguageExceptionErrorInfo);

                            if (result >= 0 && pUnk != IntPtr.Zero)
                            {
                                try
                                {
                                    // Check whether the given pUnk is a managed exception.
                                    ComCallableObject ccw;
                                    if (ComCallableObject.TryGetCCW(pUnk, out ccw))
                                    {
                                        return(ccw.TargetObject as Exception);
                                    }
                                }
                                finally
                                {
                                    McgMarshal.ComSafeRelease(pUnk);
                                }
                            }
                        }
                    }
                    String message = null, errorInfoReference = null;
                    string errMsg, errCapSid, resErrMsg;
                    int    errHr;
                    object restrictedErrorInfo = null;

                    bool hasErrorInfo = false;
                    if (RestrictedErrorInfoHelper.GetErrorDetails(pRestrictedErrorInfo, out errMsg, out errHr, out resErrMsg, out errCapSid) && errHr == hr)
                    {
                        // RestrictedErrorInfo details can be used since the pRestrictedErrorInfo has the same hr value as the hr returned by the native code.
                        // We are in windows blue or above and hence the exceptionMsg is errMsg + "\r\n" + resErrMsg
                        message = String.IsNullOrEmpty(resErrMsg) ? errMsg : errMsg + "\r\n" + resErrMsg;
                        RestrictedErrorInfoHelper.GetReference(pRestrictedErrorInfo, out errorInfoReference);
                        restrictedErrorInfo = McgMarshal.ComInterfaceToObject(pRestrictedErrorInfo, InternalTypes.IRestrictedErrorInfo);

                        hasErrorInfo = true;
                    }

                    if (hr == Interop.COM.RO_E_CLOSED && isWinRTScenario)
                    {
                        hr = Interop.COM.COR_E_OBJECTDISPOSED;
                    }

                    // Now we simply need to set the description and the resDescription by adding an internal method.
                    ex = GetMappingExceptionForHR(hr, message, isClassicCOM, hasErrorInfo);

                    if (restrictedErrorInfo != null)
                    {
                        InteropExtensions.AddExceptionDataForRestrictedErrorInfo(ex, resErrMsg, errorInfoReference, errCapSid, restrictedErrorInfo);
                    }

                    return(ex);
                }
            }
            catch (Exception)
            {
                // We can't do any thing here and hence we swallow the exception and get the corresponding hr.
            }
            finally
            {
                McgMarshal.ComSafeRelease(pRestrictedErrorInfo);
            }

            // We could not find any restrictedErrorInfo associated with this object and hence we simply use the hr to create the exception.
            return(GetMappingExceptionForHR(hr, null, isClassicCOM, hasErrorInfo: false));
        }
示例#18
0
        public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld)
        {
            if (structure == null)
            {
                throw new ArgumentNullException(nameof(structure));
            }

            if (ptr == IntPtr.Zero)
            {
                throw new ArgumentNullException(nameof(ptr));
            }

            if (fDeleteOld)
            {
                DestroyStructure(ptr, structure.GetType());
            }

            RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle;

            if (structureTypeHandle.IsGenericType() || structureTypeHandle.IsGenericTypeDefinition())
            {
                throw new ArgumentException(nameof(structure), SR.Argument_NeedNonGenericObject);
            }

            // Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0
            int offset = structureTypeHandle.IsValueType() ? 1 : 0;

            IntPtr marshalStub;

            if (structureTypeHandle.IsBlittable())
            {
                if (!RuntimeAugments.InteropCallbacks.TryGetStructMarshalStub(structureTypeHandle, out marshalStub))
                {
                    marshalStub = IntPtr.Zero;
                }
            }
            else
            {
                marshalStub = RuntimeAugments.InteropCallbacks.GetStructMarshalStub(structureTypeHandle);
            }

            if (marshalStub != IntPtr.Zero)
            {
                InteropExtensions.PinObjectAndCall(structure,
                                                   unboxedStructPtr =>
                {
                    CalliIntrinsics.Call <int>(
                        marshalStub,
                        ((void *)((IntPtr *)unboxedStructPtr + offset)),    // safe (need to adjust offset as it could be class)
                        (void *)ptr                                         // unsafe (no need to adjust as it is always struct)
                        );
                });
            }
            else
            {
                int structSize = Marshal.SizeOf(structure);
                InteropExtensions.PinObjectAndCall(structure,
                                                   unboxedStructPtr =>
                {
                    InteropExtensions.Memcpy(
                        ptr,                                                // unsafe (no need to adjust as it is always struct)
                        (IntPtr)((IntPtr *)unboxedStructPtr + offset),      // safe (need to adjust offset as it could be class)
                        structSize
                        );
                });
            }
        }