smourier / DirectN

Direct interop Code for .NET Framework, .NET Core and .NET 5+ : DXGI, WIC, DirectX 9 to 12, Direct2D, Direct Write, Direct Composition, Media Foundation, WASAPI, CodecAPI, GDI, Spatial Audio, DVD, Windows Media Player, UWP DXInterop, WinUI3, etc.
MIT License
311 stars 28 forks source link

PropVariant uncontrollable Dispose issues #53

Closed smourier closed 5 months ago

smourier commented 5 months ago

The PropVarianttype (a class) maps the native PROPVARIANT type.

However, the actual (in version 1.15.0.2 ) version clears its inner data when it's disposed (using native PropVariantClear function)

public void Dispose()
{
    _ = PropVariantClear(this);
    GC.SuppressFinalize(this);
}

The problem is when this type is declared as a parameter (in or out) of a COM method, since the way it will be freed cannot be controlled, it will just happend "at GC collection time" which can cause AV issues difficult to track.

smourier commented 5 months ago

The resolution will cause a breaking change, as we introduce the following changes:

Relevant code:

class PropVariant
{
  public virtual bool ClearOnDispose => true;

  // Detached is just a raw structure copy (doing nothing special, no AddRef on sub objects, etc.)
  public PROPVARIANT Detached => new PROPVARIANT { <copy internal data>};
  ....
  public void Dispose()
  {
      if (ClearOnDispose)
      {
          Clear(false);
      }
      GC.SuppressFinalize(this);
  }
}

public class PROPVARIANT : PropVariant
{
    public override bool ClearOnDispose => false;
    ...
}

Now, to call a COM native method like this:

HRESULT DoSomething(PROPVARIANT pv);

You'd use this:

using (var pv = new PropVariant(<something>))
{
    myObj.DoSomething(pv.Detached).ThrowOnError();
}