DragDropFormat
Represents a private format used for data transfer by the drag-and-drop helpers.
using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
using Windows.Win32.System.Memory;
using Windows.Win32.System.Ole;
namespace System.Private.Windows.Ole
{
internal class DragDropFormat : IDisposable
{
private ushort _format;
private STGMEDIUM _medium;
public STGMEDIUM Medium => _medium;
public DragDropFormat(ushort format, STGMEDIUM medium, bool copyData)
{
_format = format;
_medium = (copyData ? CopyData(format, medium) : medium);
}
public STGMEDIUM GetData()
{
return CopyData(_format, _medium);
}
public void RefreshData(ushort format, STGMEDIUM medium, bool copyData)
{
ReleaseData();
_format = format;
_medium = (copyData ? CopyData(format, medium) : medium);
}
private unsafe static STGMEDIUM CopyData(ushort format, STGMEDIUM mediumSource)
{
STGMEDIUM param = default(STGMEDIUM);
try {
switch (mediumSource.tymed) {
case TYMED.TYMED_HGLOBAL:
case TYMED.TYMED_FILE:
case TYMED.TYMED_GDI:
case TYMED.TYMED_MFPICT:
case TYMED.TYMED_ENHMF:
param.hGlobal = (HGLOBAL)(IntPtr)(void*)PInvokeCore.OleDuplicateData((HANDLE)(IntPtr)(void*)mediumSource.hGlobal, (CLIPBOARD_FORMAT)format, GLOBAL_ALLOC_FLAGS.GHND);
if (param.hGlobal.IsNull)
return default(STGMEDIUM);
break;
case TYMED.TYMED_ISTREAM:
case TYMED.TYMED_ISTORAGE:
param.hGlobal = mediumSource.hGlobal;
Marshal.AddRef(mediumSource.hGlobal);
break;
default:
param.hGlobal = HGLOBAL.Null;
break;
}
param.tymed = mediumSource.tymed;
param.pUnkForRelease = mediumSource.pUnkForRelease;
if (mediumSource.pUnkForRelease != null)
mediumSource.pUnkForRelease->AddRef();
return param;
} catch {
PInvokeCore.ReleaseStgMedium(ref param);
return default(STGMEDIUM);
}
}
private unsafe void ReleaseData()
{
PInvokeCore.ReleaseStgMedium(ref _medium);
_medium.pUnkForRelease = null;
_medium.tymed = TYMED.TYMED_NULL;
_medium.hGlobal = HGLOBAL.Null;
}
public void Dispose()
{
ReleaseData();
GC.SuppressFinalize(this);
}
~DragDropFormat()
{
Dispose();
}
}
}