diff --git a/src/System.Windows.Forms.Primitives/src/Interop/Interop.IID.cs b/src/System.Windows.Forms.Primitives/src/Interop/Interop.IID.cs index 3d3ce3a36ce..828b994f146 100644 --- a/src/System.Windows.Forms.Primitives/src/Interop/Interop.IID.cs +++ b/src/System.Windows.Forms.Primitives/src/Interop/Interop.IID.cs @@ -12,6 +12,9 @@ internal static class IID // EAC04BC0-3791-11D2-BB95-0060977B464C public static Guid IAutoComplete2 { get; } = new(0xEAC04BC0, 0x3791, 0x11D2, 0xBB, 0x95, 0x00, 0x60, 0x97, 0x7B, 0x46, 0x4C); + // 00000121-0000-0000-C000-000000000046 + public static Guid IDropSource { get; } = new(0x00000121, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + // 00000101-0000-0000-C000-000000000046 public static Guid IEnumString { get; } = new(0x00000101, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); diff --git a/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.DoDragDrop.cs b/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.DoDragDrop.cs index f06895200ad..95ea2cba029 100644 --- a/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.DoDragDrop.cs +++ b/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.DoDragDrop.cs @@ -12,8 +12,18 @@ internal static partial class Ole32 [DllImport(Libraries.Ole32, ExactSpelling = true)] public static extern HRESULT DoDragDrop( IDataObject pDataObj, - IDropSource pDropSource, + IntPtr pDropSource, DROPEFFECT dwOKEffects, out DROPEFFECT pdwEffect); + + public static HRESULT DoDragDrop( + IDataObject pDataObj, + IDropSource pDropSource, + DROPEFFECT dwOKEffects, + out DROPEFFECT pdwEffect) + { + var dropSourcePtr = WinFormsComWrappers.Instance.GetOrCreateComInterfaceForObject(pDropSource, CreateComInterfaceFlags.None); + return DoDragDrop(pDataObj, dropSourcePtr, dwOKEffects, out pdwEffect); + } } } diff --git a/src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDropSourceVtbl.cs b/src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDropSourceVtbl.cs new file mode 100644 index 00000000000..a12e5f3efe0 --- /dev/null +++ b/src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDropSourceVtbl.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal unsafe partial class WinFormsComWrappers + { + internal static class IDropSourceVtbl + { + public static IntPtr Create(IntPtr fpQueryInterface, IntPtr fpAddRef, IntPtr fpRelease) + { + IntPtr* vtblRaw = (IntPtr*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(IDropSourceVtbl), IntPtr.Size * 5); + vtblRaw[0] = fpQueryInterface; + vtblRaw[1] = fpAddRef; + vtblRaw[2] = fpRelease; + vtblRaw[3] = (IntPtr)(delegate* unmanaged)&QueryContinueDrag; + vtblRaw[4] = (IntPtr)(delegate* unmanaged)&GiveFeedback; + + return (IntPtr)vtblRaw; + } + + [UnmanagedCallersOnly] + private static HRESULT QueryContinueDrag(IntPtr thisPtr, BOOL fEscapePressed, User32.MK grfKeyState) + { + var inst = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + return inst.QueryContinueDrag(fEscapePressed, grfKeyState); + } + + [UnmanagedCallersOnly] + private static HRESULT GiveFeedback(IntPtr thisPtr, Ole32.DROPEFFECT dwEffect) + { + var inst = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + return inst.GiveFeedback(dwEffect); + } + } + } +} diff --git a/src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.cs b/src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.cs index c21ef6e0e28..0ac5945c41c 100644 --- a/src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.cs +++ b/src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.cs @@ -21,6 +21,7 @@ internal unsafe partial class WinFormsComWrappers : ComWrappers private static readonly ComInterfaceEntry* s_streamEntry = InitializeIStreamEntry(); private static readonly ComInterfaceEntry* s_fileDialogEventsEntry = InitializeIFileDialogEventsEntry(); private static readonly ComInterfaceEntry* s_enumStringEntry = InitializeIEnumStringEntry(); + private static readonly ComInterfaceEntry* s_dropSourceEntry = InitializeIDropSourceEntry(); internal static WinFormsComWrappers Instance { get; } = new WinFormsComWrappers(); @@ -62,6 +63,18 @@ private WinFormsComWrappers() { } return wrapperEntry; } + private static ComInterfaceEntry* InitializeIDropSourceEntry() + { + GetIUnknownImpl(out IntPtr fpQueryInterface, out IntPtr fpAddRef, out IntPtr fpRelease); + + IntPtr iDropSourceVtbl = IDropSourceVtbl.Create(fpQueryInterface, fpAddRef, fpRelease); + + ComInterfaceEntry* wrapperEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(WinFormsComWrappers), sizeof(ComInterfaceEntry)); + wrapperEntry->IID = IID.IDropSource; + wrapperEntry->Vtable = iDropSourceVtbl; + return wrapperEntry; + } + protected override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) { if (obj is Interop.Ole32.IStream) @@ -76,6 +89,12 @@ private WinFormsComWrappers() { } return s_fileDialogEventsEntry; } + if (obj is Ole32.IDropSource) + { + count = 1; + return s_dropSourceEntry; + } + if (obj is IEnumString) { count = 1;