Skip to content
Merged
1 change: 1 addition & 0 deletions src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<ItemGroup>
<InternalsVisibleTo Include="Avalonia.Win32.Interoperability, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.WinUI, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.IntegrationTests.Win32, PublicKey=$(AvaloniaPublicKey)" />
</ItemGroup>
<ItemGroup>
<!-- By default, any projects supports Windows, Linux, MacOS platforms. -->
Expand Down
44 changes: 44 additions & 0 deletions src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,14 @@ public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
internal static extern int CoCreateInstance(in Guid clsid,
IntPtr ignore1, int ignore2, in Guid iid, [Out] out IntPtr pUnkOuter);

[DllImport("ole32.dll", PreserveSig = true)]
internal static extern int CoMarshalInterThreadInterfaceInStream(
ref Guid riid, IntPtr unknown, out IntPtr stream);

[DllImport("ole32.dll", PreserveSig = true)]
internal static extern int CoGetInterfaceAndReleaseStream(
IntPtr stream, ref Guid riid, out IntPtr unknown);

internal static T CreateInstance<T>(in Guid clsid, in Guid iid) where T : IUnknown
{
var hresult = CoCreateInstance(in clsid, IntPtr.Zero, 1, in iid, out IntPtr pUnk);
Expand Down Expand Up @@ -2646,6 +2654,7 @@ public APPBARDATA()
public const uint DV_E_FORMATETC = 0x80040064;
public const uint OLE_E_ADVISENOTSUPPORTED = 0x80040003;
public const uint COR_E_OBJECTDISPOSED = 0x80131622;
public const int STATFLAG_NONAME = 1;

[StructLayout(LayoutKind.Sequential)]
public struct DROPFILES
Expand Down Expand Up @@ -2674,6 +2683,41 @@ public struct FORMATETC
public TYMED tymed;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal unsafe struct FILEDESCRIPTORW
{
public const uint FD_FILESIZE = 0x00000040;
public const int FileNameLength = 260;

public uint dwFlags;
public Guid clsid;
public SIZE sizel;
public POINT pointl;
public uint dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public fixed char cFileName[FileNameLength];
}

[StructLayout(LayoutKind.Sequential)]
internal struct STATSTG
{
public IntPtr pwcsName;
public uint type;
public ulong cbSize;
public FILETIME mtime;
public FILETIME ctime;
public FILETIME atime;
public uint grfMode;
public uint grfLocksSupported;
public Guid clsid;
public uint grfStateBits;
public uint reserved;
}

[Flags]
public enum GlobalAllocFlags : uint
{
Expand Down
2 changes: 1 addition & 1 deletion src/Windows/Avalonia.Win32/OleDataObjectHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ private static List<string> ReadFileNamesFromHGlobal(IntPtr hGlobal)
return files;
}

private static byte[] ReadBytesFromHGlobal(IntPtr hGlobal)
internal static byte[] ReadBytesFromHGlobal(IntPtr hGlobal)
{
var source = GlobalLock(hGlobal);
try
Expand Down
31 changes: 26 additions & 5 deletions src/Windows/Avalonia.Win32/OleDataObjectToDataTransferWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
Expand Down Expand Up @@ -33,20 +33,34 @@ protected override DataFormat[] ProvideFormats()
formats.Add(format);

bool hasSupportedImageFormat = false;
bool hasFile = false;
bool hasFileGroupDescriptor = false;
bool hasFileContents = false;

foreach (var format in formats)
{
if (ClipboardFormatRegistry.ImageFormats.Contains(format)) {
if (ClipboardFormatRegistry.ImageFormats.Contains(format))
hasSupportedImageFormat = true;
break;
}

if (DataFormat.File.Equals(format))
hasFile = true;
else if (OleVirtualFileData.FileGroupDescriptorFormat.Equals(format))
hasFileGroupDescriptor = true;
else if (OleVirtualFileData.FileContentsFormat.Equals(format))
hasFileContents = true;
}

if (hasSupportedImageFormat)
{
formats.Add(DataFormat.Bitmap);
}

// Shell virtual files have descriptors and indexed contents, but no CF_HDROP path.
if (hasFileGroupDescriptor && hasFileContents && !hasFile)
{
formats.Add(DataFormat.File);
}

return formats.ToArray();

static unsafe DataFormat? Next(IEnumFORMATETC enumFormat)
Expand Down Expand Up @@ -87,14 +101,21 @@ protected override PlatformDataTransferItem[] ProvideItems()
foreach (var storageItem in storageItems)
items.Add(PlatformDataTransferItem.Create(DataFormat.File, storageItem));
}
else if (OleVirtualFileData.TryCreateFiles(_oleDataObject) is { Count: > 0 } virtualFiles)
{
hasFiles = true;

foreach (var virtualFile in virtualFiles)
items.Add(PlatformDataTransferItem.Create(DataFormat.File, virtualFile));
}
}
else
(nonFileFormats ??= new()).Add(format);
}

// Single item containing all formats except for DataFormat.File.
if (nonFileFormats is not null)
items.Add(new OleDataObjectToDataTransferItemWrapper(_oleDataObject, Formats));
items.Add(new OleDataObjectToDataTransferItemWrapper(_oleDataObject, nonFileFormats.ToArray()));
Comment thread
YoshihiroIto marked this conversation as resolved.

return items.ToArray();
}
Expand Down
Loading