internal int GetOrCreateNativePointer(Type type, void **ppv)
        {
            if (!MicroComRuntime.GetVtableFor(type, out var vtable))
            {
                return(unchecked ((int)0x80004002u));
            }
            lock (_lock)
            {
                if (_shadows.TryGetValue(type, out var shadow))
                {
                    var targetCcw = (Ccw *)shadow;
                    AddRef(targetCcw);
                    *ppv = targetCcw;
                    return(0);
                }
                else
                {
                    var intPtr    = Marshal.AllocHGlobal(Marshal.SizeOf <Ccw>());
                    var targetCcw = (Ccw *)intPtr;
                    *   targetCcw = default;
                    targetCcw->RefCount = 0;
                    targetCcw->VTable   = vtable;
                    if (_handle == null)
                    {
                        _handle = GCHandle.Alloc(this);
                    }
                    targetCcw->GcShadowHandle = GCHandle.ToIntPtr(_handle.Value);
                    _shadows[type]            = intPtr;
                    _backShadows[intPtr]      = type;
                    *ppv = targetCcw;

                    return(0);
                }
            }
        }
        int FreeCcw(Ccw *ccw)
        {
            lock (_lock)
            {
                // Shadow got resurrected by a call to QueryInterface from another thread
                if (ccw->RefCount != 0)
                {
                    return(ccw->RefCount);
                }

                var intPtr = new IntPtr(ccw);
                var type   = _backShadows[intPtr];
                _backShadows.Remove(intPtr);
                _shadows.Remove(type);
                Marshal.FreeHGlobal(intPtr);
                if (_shadows.Count == 0)
                {
                    _handle?.Free();
                    _handle = null;
                    try
                    {
                        Target.OnUnreferencedFromNative();
                    }
                    catch (Exception e)
                    {
                        MicroComRuntime.UnhandledException(Target, e);
                    }
                }
            }

            return(0);
        }
        public T QueryInterface <T>() where T : IUnknown
        {
            var guid = MicroComRuntime.GetGuidFor(typeof(T));
            var rv   = QueryInterface(guid, out var ppv);

            if (rv == 0)
            {
                return((T)MicroComRuntime.CreateProxyFor(typeof(T), ppv, true));
            }
            throw new COMException("QueryInterface failed", rv);
        }
Exemple #4
0
 internal int QueryInterface(Ccw *ccw, Guid *guid, void **ppv)
 {
     if (MicroComRuntime.TryGetTypeForGuid(*guid, out var type))
     {
         return(QueryInterface(type, ppv));
     }
     else
     {
         return(unchecked ((int)0x80004002u));
     }
 }
        internal int AddRef(Ccw *ccw)
        {
            if (Interlocked.Increment(ref _refCount) == 1)
            {
                try
                {
                    Target.OnReferencedFromNative();
                }
                catch (Exception e)
                {
                    MicroComRuntime.UnhandledException(Target, e);
                }
            }

            return(Interlocked.Increment(ref ccw->RefCount));
        }
 internal int QueryInterface(Ccw *ccw, Guid *guid, void **ppv)
 {
     if (MicroComRuntime.TryGetTypeForGuid(*guid, out var type))
     {
         return(QueryInterface(type, ppv));
     }
     else if (*guid == MicroComRuntime.ManagedObjectInterfaceGuid)
     {
         ccw->RefCount++;
         *ppv = ccw;
         return(0);
     }
     else
     {
         return(unchecked ((int)0x80004002u));
     }
 }