예제 #1
0
        // simply check if a COM object supports a particular COM interface
        // (without doing any casting by the CLR, which does much more than this under the covers)
        public static bool DoesComObjPtrSupportInterface <T>(IntPtr comObjPtr)
        {
            var iid = typeof(T).GUID;
            var hr  = RdMarshal.QueryInterface(comObjPtr, ref iid, out var outInterfacePtr);

            if (!ComHelper.HRESULT_FAILED(hr))
            {
                RdMarshal.Release(outInterfacePtr);
                return(true);
            }
            return(false);
        }
예제 #2
0
        private void TraceRelease(int rcwCount, ref bool addRef)
        {
            if (!addRef)
            {
                // Temporarily add a ref so that we can safely call IUnknown::Release
                // to report the ref count in the log.
                RdMarshal.AddRef(_pUnk);
            }
            var refCount = RdMarshal.Release(_pUnk);

            Debug.Print($"ComPointer:: Disposed: _pUnk: {RdMarshal.FormatPtr(_pUnk)} _interface: {typeof(TComInterface).Name} - {Interface.GetHashCode()} addRef: {_addRef} rcwCount: {rcwCount} refCount: {refCount}");

            addRef = false;
        }
예제 #3
0
        private void ReleaseUnmanagedResources()
        {
            if (_disposed)
            {
                return;
            }

            var rcwCount = RdMarshal.ReleaseComObject(Interface);
            var addRef   = _addRef;

            TraceRelease(rcwCount, ref addRef);
            if (addRef)
            {
                RdMarshal.Release(_pUnk);
            }

            _disposed = true;
        }
예제 #4
0
        void ComTypes.ITypeInfo.CreateInstance(object pUnkOuter, ref Guid riid, out object ppvObj)
        {
            // initialize out parameters
            ppvObj = default;

            using (var outPpvObj = AddressableVariables.CreateObjectPtr <object>())
            {
                var unkOuter = RdMarshal.GetIUnknownForObject(pUnkOuter);
                var hr       = _this_Internal.CreateInstance(unkOuter, riid, outPpvObj.Address);
                RdMarshal.Release(unkOuter);
                if (ComHelper.HRESULT_FAILED(hr))
                {
                    HandleBadHRESULT(hr);
                }

                ppvObj = outPpvObj.Value;
            }
        }
예제 #5
0
        /// <summary>
        /// Takes a COM object, and reads the unmanaged memory given by its pointer, allowing us to read internal fields
        /// </summary>
        /// <typeparam name="T">the type of structure to return</typeparam>
        /// <param name="comObj">the COM object</param>
        /// <returns>the requested structure T</returns>
        public static T ReadComObjectStructure <T>(object comObj)
        {
            // Reads a COM object as a structure to copy its internal fields
            if (!RdMarshal.IsComObject(comObj))
            {
                throw new ArgumentException("Expected a COM object");
            }

            var referencesPtr = RdMarshal.GetIUnknownForObjectInContext(comObj);

            if (referencesPtr == IntPtr.Zero)
            {
                throw new InvalidOperationException("Cannot access the TypeLib API from this thread.  TypeLib API must be accessed from the main thread.");
            }
            var retVal = ReadStructureSafe <T>(referencesPtr);

            RdMarshal.Release(referencesPtr);
            return(retVal);
        }
예제 #6
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="outerObject">The object that needs interface requests filtered</param>
        /// <param name="queryForType">determines whether we call QueryInterface for the interface or not</param>
        /// <remarks>if the passed in outerObject is known to point to the correct vtable for the interface, then queryForType can be false</remarks>
        /// <returns>if outerObject is IntPtr.Zero, then a null wrapper, else an aggregated wrapper</returns>
        public RestrictComInterfaceByAggregation(IntPtr outerObject, bool queryForType = true)
        {
            if (queryForType)
            {
                var iid = typeof(T).GUID;
                if (ComHelper.HRESULT_FAILED(RdMarshal.QueryInterface(outerObject, ref iid, out _outerObject)))
                {
                    // allow null wrapping here
                    return;
                }
            }
            else
            {
                _outerObject = outerObject;
                RdMarshal.AddRef(_outerObject);
            }

            var clrAggregator = RdMarshal.CreateAggregatedObject(_outerObject, this);

            WrappedObject = (T)RdMarshal.GetObjectForIUnknown(clrAggregator); // when this CCW object gets released, it will free the aggObjInner (well, after GC)
            RdMarshal.Release(clrAggregator);                                 // _wrappedObject holds a reference to this now
        }
예제 #7
0
        protected virtual void Dispose(bool disposing)
        {
            if (_isDisposed || !disposing)
            {
                return;
            }
            _isDisposed = true;

            if (WrappedObject != null)
            {
                RdMarshal.ReleaseComObject(WrappedObject);
            }

            if (_outerObject != IntPtr.Zero)
            {
                RdMarshal.Release(_outerObject);

                // dont set _outerObject to IntPtr.Zero here, as GetInterface() can still be called by the outer RCW
                // if it is still alive. For example, if ExtractWrappedObject was used and the outer object hasn't yet
                // been released with ReleaseComObject.  In that circumstance _outerObject will still be a valid pointer
                // due to the internally held reference, and so GetInterface() calls past this point are still OK.
            }
        }