| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- using System;
- using System.Runtime.ConstrainedExecution;
- using System.Runtime.InteropServices;
- using System.Threading;
- namespace Avalonia.MicroCom
- {
- public unsafe class MicroComProxyBase : CriticalFinalizerObject, IUnknown
- {
- private IntPtr _nativePointer;
- private bool _ownsHandle;
- private SynchronizationContext _synchronizationContext;
- public IntPtr NativePointer
- {
- get
- {
- if (_nativePointer == IntPtr.Zero)
- throw new ObjectDisposedException(this.GetType().FullName);
- return _nativePointer;
- }
- }
- public void*** PPV => (void***)NativePointer;
- public MicroComProxyBase(IntPtr nativePointer, bool ownsHandle)
- {
- _nativePointer = nativePointer;
- _ownsHandle = ownsHandle;
- _synchronizationContext = SynchronizationContext.Current;
- if(!_ownsHandle)
- GC.SuppressFinalize(this);
- }
- protected virtual int VTableSize => 3;
-
- public void AddRef()
- {
- LocalInterop.CalliStdCallvoid(PPV, (*PPV)[1]);
- }
- public void Release()
- {
- LocalInterop.CalliStdCallvoid(PPV, (*PPV)[2]);
- }
- public int QueryInterface(Guid guid, out IntPtr ppv)
- {
- IntPtr r = default;
- var rv = LocalInterop.CalliStdCallint(PPV, &guid, &r, (*PPV)[0]);
- ppv = r;
- return rv;
- }
- 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);
- }
- public bool IsDisposed => _nativePointer == IntPtr.Zero;
- protected virtual void Dispose(bool disposing)
- {
- if(_nativePointer == null)
- return;
- if (_ownsHandle)
- {
- Release();
- _ownsHandle = false;
- }
- _nativePointer = IntPtr.Zero;
- GC.SuppressFinalize(this);
- }
-
- public void Dispose() => Dispose(true);
- public bool OwnsHandle => _ownsHandle;
-
- public void EnsureOwned()
- {
- if (!_ownsHandle)
- {
- GC.ReRegisterForFinalize(true);
- AddRef();
- _ownsHandle = true;
- }
- }
- private static readonly SendOrPostCallback _disposeDelegate = DisposeOnContext;
- private static void DisposeOnContext(object state)
- {
- (state as MicroComProxyBase)?.Dispose(false);
- }
- ~MicroComProxyBase()
- {
- if(!_ownsHandle)
- return;
- if (_synchronizationContext == null)
- Dispose();
- else
- _synchronizationContext.Post(_disposeDelegate, this);
- }
- }
- }
|