mirror of
https://gitee.com/csharpui/CPF.git
synced 2026-04-17 11:08:03 +08:00
初始化
This commit is contained in:
113
CPF.Windows/MicroCom/MicroComProxyBase.cs
Normal file
113
CPF.Windows/MicroCom/MicroComProxyBase.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace CPF.Windows.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user