Skip to content

Commit 1feda3d

Browse files
committed
Restructure DataObject
1 parent 194388c commit 1feda3d

File tree

67 files changed

+2900
-1235
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2900
-1235
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
[assembly: SuppressMessage("Usage", "CA2201:Do not raise reserved exception types", Justification = "Compat", Scope = "member", Target = "~M:System.Private.Windows.Core.OLE.DesktopDataObject.Composition.NativeToDesktopAdapter.ReadByteStreamFromHGLOBAL(Windows.Win32.Foundation.HGLOBAL,System.Boolean@)~System.IO.MemoryStream")]
5+
[assembly: SuppressMessage("Usage", "CA2201:Do not raise reserved exception types", Justification = "Compat", Scope = "member", Target = "~M:System.Private.Windows.Core.OLE.DesktopDataObject.Composition.NativeToRuntimeAdapter.System#Runtime#InteropServices#ComTypes#IDataObject#EnumFormatEtc(System.Runtime.InteropServices.ComTypes.DATADIR)~System.Runtime.InteropServices.ComTypes.IEnumFORMATETC")]
6+
[assembly: SuppressMessage("Usage", "CA2201:Do not raise reserved exception types", Justification = "Compat", Scope = "member", Target = "~M:System.Private.Windows.Core.OLE.DesktopClipboard.SetDataObject(System.Object,System.Boolean,System.Int32,System.Int32)")]
7+
[assembly: SuppressMessage("Usage", "CA2201:Do not raise reserved exception types", Justification = "Compat", Scope = "member", Target = "~M:System.Private.Windows.Core.OLE.DesktopClipboard.GetDataObject~System.Private.Windows.Core.OLE.IDataObjectDesktop")]

src/System.Private.Windows.Core/src/NativeMethods.txt

+17
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ BeginPaint
22
BI_COMPRESSION
33
BitBlt
44
BOOL
5+
CFSTR_DROPDESCRIPTION
6+
CFSTR_INDRAGLOOP
57
CLIPBRD_E_BAD_DATA
68
CLR_*
79
CallWindowProc
810
CoCreateInstance
911
CombineRgn
1012
CopyImage
13+
CP_ACP
1114
CreateBitmap
1215
CreateCompatibleBitmap
1316
CreateCompatibleDC
@@ -50,7 +53,11 @@ DRAGDROP_S_CANCEL
5053
DRAGDROP_S_DROP
5154
DRAGDROP_S_USEDEFAULTCURSORS
5255
DrawIconEx
56+
DragQueryFile
57+
DROPDESCRIPTION
58+
DROPFILES
5359
DV_E_*
60+
DVASPECT
5461
E_ABORT
5562
E_ACCESSDENIED
5663
E_FAIL
@@ -78,6 +85,7 @@ GetWindowText
7885
GetWindowTextLength
7986
GET_CLASS_LONG_INDEX
8087
GetClientRect
88+
GetClipboardFormatName
8189
GetClipRgn
8290
GetDC
8391
GetDCEx
@@ -119,7 +127,9 @@ HPROPSHEETPAGE
119127
HRGN
120128
HWND
121129
HWND_*
130+
IDataObject
122131
IDI_*
132+
IDragSourceHelper2
123133
IEnumUnknown
124134
IGlobalInterfaceTable
125135
ImageLockMode
@@ -162,6 +172,10 @@ OLE_E_INVALIDRECT
162172
OLE_E_NOCONNECTION
163173
OLE_E_PROMPTSAVECANCELLED
164174
OleCreatePictureIndirect
175+
OleDuplicateData
176+
OleFlushClipboard
177+
OleGetClipboard
178+
OleSetClipboard
165179
PeekMessage
166180
PostMessage
167181
POINTS
@@ -171,7 +185,9 @@ PWSTR
171185
RealizePalette
172186
RECT
173187
REGDB_E_CLASSNOTREG
188+
RegisterClipboardFormat
174189
ReleaseDC
190+
ReleaseStgMedium
175191
RestoreDC
176192
RPC_E_CHANGED_MODE
177193
RPC_E_DISCONNECTED
@@ -215,6 +231,7 @@ SystemParametersInfoForDpi
215231
TYPE_E_BADMODULEKIND
216232
UNICODE_STRING_MAX_CHARS
217233
VIEW_E_DRAW
234+
WideCharToMultiByte
218235
WIN32_ERROR
219236
WINCODEC_ERR_*
220237
WINDOW_LONG_PTR_INDEX

src/System.Private.Windows.Core/src/OLE/Clipboard.cs src/System.Private.Windows.Core/src/OLE/DesktopClipboard.cs

+128-145
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace System.Private.Windows.Core.OLE;
5+
6+
/// <summary>
7+
/// Translates between WinForms text-based <see cref="DesktopClipboard"/>
8+
/// formats and Win32 32-bit signed integer-based clipboard
9+
/// formats. Provides <see langword="static"/> methods to create new
10+
/// <see cref="DesktopClipboard"/> formats and add them to the Windows Registry.
11+
/// </summary>
12+
internal static partial class DesktopDataFormats
13+
{
14+
/// <summary>
15+
/// Represents a format type.
16+
/// </summary>
17+
public class Format
18+
{
19+
/// <summary>
20+
/// Initializes a new instance of the <see cref="Format"/> class and
21+
/// specifies whether a Win32 handle is expected with this format.
22+
/// </summary>
23+
public Format(string name, int id)
24+
{
25+
Name = name;
26+
Id = id;
27+
}
28+
29+
/// <summary>
30+
/// Specifies the name of this format.
31+
/// </summary>
32+
public string Name { get; }
33+
34+
/// <summary>
35+
/// Specifies the ID number for this format.
36+
/// </summary>
37+
public int Id { get; }
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.ComponentModel;
5+
using System.Private.Windows.Core.Resources;
6+
using System.Runtime.InteropServices;
7+
using Windows.Win32;
8+
using Windows.Win32.System.Ole;
9+
10+
namespace System.Private.Windows.Core.OLE;
11+
12+
/// <summary>
13+
/// Translates between WinForms text-based <see cref="DesktopClipboard"/>
14+
/// formats and Win32 32-bit signed integer-based clipboard
15+
/// formats. Provides <see langword="static"/> methods to create new
16+
/// <see cref="DesktopClipboard"/> formats and add them to the Windows Registry.
17+
/// </summary>
18+
internal static partial class DesktopDataFormats
19+
{
20+
internal const string TextConstant = "Text";
21+
internal const string UnicodeTextConstant = "UnicodeText";
22+
internal const string DibConstant = "DeviceIndependentBitmap";
23+
internal const string BitmapConstant = "Bitmap";
24+
internal const string EmfConstant = "EnhancedMetafile";
25+
internal const string WmfConstant = "MetaFilePict";
26+
internal const string SymbolicLinkConstant = "SymbolicLink";
27+
internal const string DifConstant = "DataInterchangeFormat";
28+
internal const string TiffConstant = "TaggedImageFileFormat";
29+
internal const string OemTextConstant = "OEMText";
30+
internal const string PaletteConstant = "Palette";
31+
internal const string PenDataConstant = "PenData";
32+
internal const string RiffConstant = "RiffAudio";
33+
internal const string WaveAudioConstant = "WaveAudio";
34+
internal const string FileDropConstant = "FileDrop";
35+
internal const string LocaleConstant = "Locale";
36+
internal const string HtmlConstant = "HTML Format";
37+
internal const string RtfConstant = "Rich Text Format";
38+
internal const string CsvConstant = "Csv";
39+
internal const string StringConstant = "System.String";
40+
internal const string SerializableConstant = "WindowsForms10PersistentObject";
41+
42+
private static Format[]? s_formatList;
43+
44+
private static int s_formatCount;
45+
46+
#if NET9_0_OR_GREATER
47+
private static readonly Lock s_internalSyncObject = new();
48+
#else
49+
private static readonly object s_internalSyncObject = new();
50+
#endif
51+
52+
/// <summary>
53+
/// Gets a <see cref="Format"/> with the Windows Clipboard numeric ID and name for the specified format.
54+
/// </summary>
55+
public static Format GetFormat(string format)
56+
{
57+
ArgumentException.ThrowIfNullOrWhiteSpace(format);
58+
59+
lock (s_internalSyncObject)
60+
{
61+
EnsurePredefined();
62+
63+
// It is much faster to do a case sensitive search here.
64+
// So do the case sensitive compare first, then the expensive one.
65+
for (int n = 0; n < s_formatCount; n++)
66+
{
67+
if (s_formatList[n].Name.Equals(format))
68+
{
69+
return s_formatList[n];
70+
}
71+
}
72+
73+
for (int n = 0; n < s_formatCount; n++)
74+
{
75+
if (string.Equals(s_formatList[n].Name, format, StringComparison.OrdinalIgnoreCase))
76+
{
77+
return s_formatList[n];
78+
}
79+
}
80+
81+
// Need to add this format string
82+
uint formatId = PInvokeCore.RegisterClipboardFormat(format);
83+
if (formatId == 0)
84+
{
85+
throw new Win32Exception(Marshal.GetLastWin32Error(), SR.RegisterCFFailed);
86+
}
87+
88+
EnsureFormatSpace(1);
89+
s_formatList[s_formatCount] = new Format(format, (int)formatId);
90+
return s_formatList[s_formatCount++];
91+
}
92+
}
93+
94+
/// <summary>
95+
/// Gets a <see cref="Format"/> with the Windows Clipboard numeric ID and name for the specified ID.
96+
/// </summary>
97+
internal static unsafe Format GetFormat(ushort id)
98+
{
99+
lock (s_internalSyncObject)
100+
{
101+
EnsurePredefined();
102+
103+
for (int n = 0; n < s_formatCount; n++)
104+
{
105+
if (s_formatList[n].Id == id)
106+
{
107+
return s_formatList[n];
108+
}
109+
}
110+
111+
string? name = null;
112+
113+
// The max length of the name of clipboard formats is equal to the max length
114+
// of a Win32 Atom of 255 chars. An additional null terminator character is added,
115+
// giving a required capacity of 256 chars.
116+
Span<char> formatName = stackalloc char[256];
117+
fixed (char* pFormatName = formatName)
118+
{
119+
int length = PInvokeCore.GetClipboardFormatName(id, pFormatName, 256);
120+
if (length != 0)
121+
{
122+
name = formatName[..length].ToString();
123+
}
124+
}
125+
126+
// This can happen if windows adds a standard format that we don't know about,
127+
// so we should play it safe.
128+
name ??= $"Format{id}";
129+
130+
EnsureFormatSpace(1);
131+
s_formatList[s_formatCount] = new Format(name, id);
132+
return s_formatList[s_formatCount++];
133+
}
134+
}
135+
136+
/// <summary>
137+
/// Ensures that we have enough room in our format list
138+
/// </summary>
139+
[MemberNotNull(nameof(s_formatList))]
140+
private static void EnsureFormatSpace(int size)
141+
{
142+
if (s_formatList is null || s_formatList.Length <= s_formatCount + size)
143+
{
144+
int newSize = s_formatCount + 20;
145+
146+
Format[] newList = new Format[newSize];
147+
for (int n = 0; n < s_formatCount; n++)
148+
{
149+
newList[n] = s_formatList![n];
150+
}
151+
152+
s_formatList = newList;
153+
}
154+
}
155+
156+
/// <summary>
157+
/// Ensures that the Win32 predefined formats are setup in our format list.
158+
/// This is called anytime we need to search the list
159+
/// </summary>
160+
[MemberNotNull(nameof(s_formatList))]
161+
private static void EnsurePredefined()
162+
{
163+
if (s_formatCount == 0)
164+
{
165+
s_formatList =
166+
[
167+
// Text name Win32 format ID
168+
new(UnicodeTextConstant, (int)CLIPBOARD_FORMAT.CF_UNICODETEXT),
169+
new(TextConstant, (int)CLIPBOARD_FORMAT.CF_TEXT),
170+
new(BitmapConstant, (int)CLIPBOARD_FORMAT.CF_BITMAP),
171+
new(WmfConstant, (int)CLIPBOARD_FORMAT.CF_METAFILEPICT),
172+
new(EmfConstant, (int)CLIPBOARD_FORMAT.CF_ENHMETAFILE),
173+
new(DifConstant, (int)CLIPBOARD_FORMAT.CF_DIF),
174+
new(TiffConstant, (int)CLIPBOARD_FORMAT.CF_TIFF),
175+
new(OemTextConstant, (int)CLIPBOARD_FORMAT.CF_OEMTEXT),
176+
new(DibConstant, (int)CLIPBOARD_FORMAT.CF_DIB),
177+
new(PaletteConstant, (int)CLIPBOARD_FORMAT.CF_PALETTE),
178+
new(PenDataConstant, (int)CLIPBOARD_FORMAT.CF_PENDATA),
179+
new(RiffConstant, (int)CLIPBOARD_FORMAT.CF_RIFF),
180+
new(WaveAudioConstant, (int)CLIPBOARD_FORMAT.CF_WAVE),
181+
new(SymbolicLinkConstant, (int)CLIPBOARD_FORMAT.CF_SYLK),
182+
new(FileDropConstant, (int)CLIPBOARD_FORMAT.CF_HDROP),
183+
new(LocaleConstant, (int)CLIPBOARD_FORMAT.CF_LOCALE)
184+
];
185+
186+
s_formatCount = s_formatList.Length;
187+
}
188+
else
189+
{
190+
s_formatList ??= [];
191+
}
192+
}
193+
}

0 commit comments

Comments
 (0)