|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Com = Windows.Win32.System.Com;
using ComTypes = System.Runtime.InteropServices.ComTypes;
namespace System.Windows.Forms;
public unsafe partial class DataObject
{
internal unsafe partial class Composition
{
/// <summary>
/// Maps native pointer <see cref="Com.IDataObject"/> to <see cref="ComTypes.IDataObject"/>.
/// </summary>
private class NativeToRuntimeAdapter : ComTypes.IDataObject
{
private readonly AgileComPointer<Com.IDataObject> _nativeDataObject;
public NativeToRuntimeAdapter(Com.IDataObject* dataObject)
{
#if DEBUG
_nativeDataObject = new(dataObject, takeOwnership: true, trackDisposal: false);
#else
_nativeDataObject = new(dataObject, takeOwnership: true);
#endif
}
int ComTypes.IDataObject.DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection)
{
using var nativeAdviseSink = ComHelpers.TryGetComScope<Com.IAdviseSink>(adviseSink);
fixed (Com.FORMATETC* nativeFormat = &Unsafe.As<FORMATETC, Com.FORMATETC>(ref pFormatetc))
fixed (int* pConnection = &connection)
{
using var nativeDataObject = _nativeDataObject.GetInterface();
return nativeDataObject.Value->DAdvise(nativeFormat, (uint)advf, nativeAdviseSink, (uint*)pConnection);
}
}
void ComTypes.IDataObject.DUnadvise(int connection)
{
using var nativeDataObject = _nativeDataObject.GetInterface();
nativeDataObject.Value->DUnadvise((uint)connection).ThrowOnFailure();
}
int ComTypes.IDataObject.EnumDAdvise(out IEnumSTATDATA? enumAdvise)
{
using ComScope<Com.IEnumSTATDATA> nativeStatData = new(null);
using var nativeDataObject = _nativeDataObject.GetInterface();
HRESULT result = nativeDataObject.Value->EnumDAdvise(nativeStatData);
ComHelpers.TryGetObjectForIUnknown(nativeStatData.AsUnknown, out enumAdvise);
return result;
}
IEnumFORMATETC ComTypes.IDataObject.EnumFormatEtc(DATADIR direction)
{
using ComScope<Com.IEnumFORMATETC> nativeFormat = new(null);
using var nativeDataObject = _nativeDataObject.GetInterface();
if (nativeDataObject.Value->EnumFormatEtc((uint)direction, nativeFormat).Failed)
{
throw new ExternalException(SR.ExternalException, (int)HRESULT.E_NOTIMPL);
}
return (IEnumFORMATETC)ComHelpers.GetObjectForIUnknown(nativeFormat);
}
int ComTypes.IDataObject.GetCanonicalFormatEtc(ref FORMATETC formatIn, out FORMATETC formatOut)
{
using var nativeDataObject = _nativeDataObject.GetInterface();
HRESULT result = nativeDataObject.Value->GetCanonicalFormatEtc(Unsafe.As<FORMATETC, Com.FORMATETC>(ref formatIn), out Com.FORMATETC nativeFormat);
formatOut = Unsafe.As<Com.FORMATETC, FORMATETC>(ref nativeFormat);
return result;
}
void ComTypes.IDataObject.GetData(ref FORMATETC format, out STGMEDIUM medium)
{
Com.FORMATETC nativeFormat = Unsafe.As<FORMATETC, Com.FORMATETC>(ref format);
Com.STGMEDIUM nativeMedium = default;
using var nativeDataObject = _nativeDataObject.GetInterface();
nativeDataObject.Value->GetData(&nativeFormat, &nativeMedium).ThrowOnFailure();
medium = (STGMEDIUM)nativeMedium;
nativeMedium.ReleaseUnknown();
}
void ComTypes.IDataObject.GetDataHere(ref FORMATETC format, ref STGMEDIUM medium)
{
Com.FORMATETC nativeFormat = Unsafe.As<FORMATETC, Com.FORMATETC>(ref format);
Com.STGMEDIUM nativeMedium = (Com.STGMEDIUM)medium;
using var nativeDataObject = _nativeDataObject.GetInterface();
nativeDataObject.Value->GetDataHere(&nativeFormat, &nativeMedium).ThrowOnFailure();
medium = (STGMEDIUM)nativeMedium;
nativeMedium.ReleaseUnknown();
}
int ComTypes.IDataObject.QueryGetData(ref FORMATETC format)
{
using var nativeDataObject = _nativeDataObject.GetInterface();
return nativeDataObject.Value->QueryGetData(Unsafe.As<FORMATETC, Com.FORMATETC>(ref format));
}
void ComTypes.IDataObject.SetData(ref FORMATETC formatIn, ref STGMEDIUM medium, bool release)
{
Com.STGMEDIUM nativeMedium = (Com.STGMEDIUM)medium;
Com.FORMATETC nativeFormat = Unsafe.As<FORMATETC, Com.FORMATETC>(ref formatIn);
using var nativeDataObject = _nativeDataObject.GetInterface();
HRESULT result = nativeDataObject.Value->SetData(&nativeFormat, &nativeMedium, release);
medium = (STGMEDIUM)nativeMedium;
nativeMedium.ReleaseUnknown();
result.ThrowOnFailure();
}
}
}
}
|