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); }
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)); } }