Skip to content

Commit 620b123

Browse files
authored
More OLE related refactoring (#12840)
This makes a number of changes to continue the move of OLE code to Core. - Move clipboard related switch to Core - Move CsWin32 definitions to Core - Rename older PInvokeCore files - Unnest a few more classes - Move FeatureSwitchDefinition to FeatureSwitches - Move JsonData to Core - Move TypeExtensions to Core Note that setting `typeof()` to a static actually results in lower perf. `typeof()` gets replaced with a pointer by the JIT.
1 parent cc8aabe commit 620b123

File tree

81 files changed

+810
-772
lines changed

Some content is hidden

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

81 files changed

+810
-772
lines changed

src/Common/tests/TestUtilities/AppContextSwitchScope.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Reflection;
5+
46
namespace System;
57

68
/// <summary>
@@ -18,7 +20,7 @@ public readonly ref struct AppContextSwitchScope
1820
private readonly bool _originalState;
1921

2022
public AppContextSwitchScope(string switchName, bool enable)
21-
: this (switchName, getDefaultValue: null, enable)
23+
: this(switchName, getDefaultValue: null, enable)
2224
{
2325
}
2426

@@ -31,6 +33,7 @@ public AppContextSwitchScope(string switchName, Func<bool>? getDefaultValue, boo
3133
throw new InvalidOperationException("LocalAppContext switch caching is not disabled.");
3234
}
3335

36+
// AppContext won't have any switch value until it is explicitly set.
3437
if (!AppContext.TryGetSwitch(switchName, out _originalState))
3538
{
3639
_originalState = getDefaultValue is not null && getDefaultValue();
@@ -53,4 +56,23 @@ public void Dispose()
5356
throw new InvalidOperationException($"Could not reset {_switchName} to {_originalState}.");
5457
}
5558
}
59+
60+
/// <summary>
61+
/// Gets the default value for a switch via reflection.
62+
/// </summary>
63+
public static bool GetDefaultValueForSwitchInAssembly(string switchName, string assemblyName, string typeName)
64+
{
65+
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
66+
{
67+
if (assembly.GetName().Name == assemblyName)
68+
{
69+
Type type = assembly.GetType(typeName)
70+
?? throw new InvalidOperationException($"Could not find {typeName} type in {assemblyName} assembly.");
71+
72+
return type.TestAccessor().Dynamic.GetSwitchDefaultValue(switchName);
73+
}
74+
}
75+
76+
throw new InvalidOperationException($"Could not find {assemblyName} assembly in the test process.");
77+
}
5678
}

src/Common/tests/TestUtilities/BinaryFormatterInClipboardDragDropScope.cs

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ public readonly ref struct BinaryFormatterInClipboardDragDropScope
1010
public BinaryFormatterInClipboardDragDropScope(bool enable)
1111
{
1212
Monitor.Enter(typeof(BinaryFormatterInClipboardDragDropScope));
13-
_switchScope = new(AppContextSwitchNames.ClipboardDragDropEnableUnsafeBinaryFormatterSerializationSwitchName, GetDefaultValue, enable);
13+
_switchScope = new(
14+
AppContextSwitchNames.ClipboardDragDropEnableUnsafeBinaryFormatterSerializationSwitchName,
15+
() => AppContextSwitchScope.GetDefaultValueForSwitchInAssembly(
16+
AppContextSwitchNames.ClipboardDragDropEnableUnsafeBinaryFormatterSerializationSwitchName,
17+
"System.Private.Windows.Core",
18+
"System.Private.Windows.CoreAppContextSwitches"),
19+
enable);
1420
}
1521

1622
public void Dispose()
@@ -24,23 +30,4 @@ public void Dispose()
2430
Monitor.Exit(typeof(BinaryFormatterInClipboardDragDropScope));
2531
}
2632
}
27-
28-
internal static bool GetDefaultValue()
29-
{
30-
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
31-
foreach (var assembly in assemblies)
32-
{
33-
if (assembly.FullName?.StartsWith("System.Windows.Forms.Primitives,", StringComparison.InvariantCultureIgnoreCase) == true)
34-
{
35-
var type = assembly.GetType("System.Windows.Forms.Primitives.LocalAppContextSwitches")
36-
?? throw new InvalidOperationException("Could not find LocalAppContextSwitches type in System.Windows.Forms.Primitives assembly.");
37-
38-
bool value = type.TestAccessor().CreateDelegate<Func<string, bool>>("GetSwitchDefaultValue")
39-
(AppContextSwitchNames.ClipboardDragDropEnableUnsafeBinaryFormatterSerializationSwitchName);
40-
return value;
41-
}
42-
}
43-
44-
throw new InvalidOperationException("Could not find System.Windows.Forms.Primitives assembly in the test process.");
45-
}
4633
}

src/Common/tests/TestUtilities/NrbfSerializerInClipboardDragDropScope.cs

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ public readonly ref struct NrbfSerializerInClipboardDragDropScope
1010
public NrbfSerializerInClipboardDragDropScope(bool enable)
1111
{
1212
Monitor.Enter(typeof(NrbfSerializerInClipboardDragDropScope));
13-
_switchScope = new(AppContextSwitchNames.ClipboardDragDropEnableNrbfSerializationSwitchName, GetDefaultValue, enable);
13+
_switchScope = new(
14+
AppContextSwitchNames.ClipboardDragDropEnableNrbfSerializationSwitchName,
15+
() => AppContextSwitchScope.GetDefaultValueForSwitchInAssembly(
16+
AppContextSwitchNames.ClipboardDragDropEnableNrbfSerializationSwitchName,
17+
"System.Private.Windows.Core",
18+
"System.Private.Windows.CoreAppContextSwitches"),
19+
enable);
1420
}
1521

1622
public void Dispose()
@@ -24,23 +30,4 @@ public void Dispose()
2430
Monitor.Exit(typeof(NrbfSerializerInClipboardDragDropScope));
2531
}
2632
}
27-
28-
internal static bool GetDefaultValue()
29-
{
30-
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
31-
foreach (var assembly in assemblies)
32-
{
33-
if (assembly.FullName?.StartsWith("System.Windows.Forms.Primitives,", StringComparison.InvariantCultureIgnoreCase) == true)
34-
{
35-
var type = assembly.GetType("System.Windows.Forms.Primitives.LocalAppContextSwitches")
36-
?? throw new InvalidOperationException("Could not find LocalAppContextSwitches type in System.Windows.Forms.Primitives assembly.");
37-
38-
bool value = type.TestAccessor().CreateDelegate<Func<string, bool>>("GetSwitchDefaultValue")
39-
(AppContextSwitchNames.ClipboardDragDropEnableNrbfSerializationSwitchName);
40-
return value;
41-
}
42-
}
43-
44-
throw new InvalidOperationException("Could not find System.Windows.Forms.Primitives assembly in the test process.");
45-
}
4633
}

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

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ BeginPaint
22
BI_COMPRESSION
33
BitBlt
44
BOOL
5-
CLIPBRD_E_BAD_DATA
6-
CLR_*
75
CallWindowProc
6+
CFSTR_DROPDESCRIPTION
7+
CFSTR_INDRAGLOOP
88
CLIPBOARD_FORMAT
9+
CLIPBRD_E_BAD_DATA
10+
CLR_*
911
CoCreateInstance
1012
CombineRgn
1113
CopyImage
14+
CP_ACP
1215
CreateBitmap
1316
CreateCompatibleBitmap
1417
CreateCompatibleDC
@@ -45,12 +48,18 @@ DISP_E_UNKNOWNLCID
4548
DISP_E_UNKNOWNNAME
4649
DISPID_*
4750
DMORIENT_*
51+
DoDragDrop
52+
DragAcceptFiles
4853
DRAGDROP_E_ALREADYREGISTERED
4954
DRAGDROP_E_NOTREGISTERED
5055
DRAGDROP_S_CANCEL
5156
DRAGDROP_S_DROP
5257
DRAGDROP_S_USEDEFAULTCURSORS
58+
DragQueryFile
5359
DrawIconEx
60+
DROPDESCRIPTION
61+
DROPFILES
62+
DROPIMAGETYPE
5463
DV_E_*
5564
E_ABORT
5665
E_ACCESSDENIED
@@ -73,14 +82,11 @@ FACILITY_CODE
7382
fdex*
7483
FDEX_PROP_FLAGS
7584
FILETIME
76-
GetCurrentThreadId
77-
GetSysColorBrush
78-
GetWindowText
79-
GetWindowTextLength
8085
GET_CLASS_LONG_INDEX
8186
GetClientRect
8287
GetClipboardFormatName
8388
GetClipRgn
89+
GetCurrentThreadId
8490
GetDC
8591
GetDCEx
8692
GetDesktopWindow
@@ -94,12 +100,17 @@ GetObjectType
94100
GetPaletteEntries
95101
GetRegionData
96102
GetStockObject
103+
GetSysColor
104+
GetSysColorBrush
97105
GetSystemDefaultLCID
98106
GetSystemMetrics
99107
GetThreadLocale
100108
GetViewportExtEx
101109
GetViewportOrgEx
102110
GetWindowRect
111+
GetWindowText
112+
GetWindowTextLength
113+
GetWindowThreadProcessId
103114
GlobalAlloc
104115
GlobalFree
105116
GlobalLock
@@ -121,7 +132,9 @@ HPROPSHEETPAGE
121132
HRGN
122133
HWND
123134
HWND_*
135+
IDataObject
124136
IDI_*
137+
IDragSourceHelper2
125138
IEnumUnknown
126139
IGlobalInterfaceTable
127140
ImageLockMode
@@ -145,37 +158,47 @@ MonitorFromRect
145158
MonitorFromWindow
146159
MONITORINFOEXW
147160
MONITORINFOF_*
161+
MultiByteToWideChar
148162
NONCLIENTMETRICSW
149-
NS_E_WMP_URLDOWNLOADFAILED
150-
NS_E_WMP_LOGON_FAILURE
151163
NS_E_WMP_CANNOT_FIND_FILE
152-
NS_E_WMP_UNSUPPORTED_FORMAT
153164
NS_E_WMP_DSHOW_UNSUPPORTED_FORMAT
154165
NS_E_WMP_INVALID_ASX
166+
NS_E_WMP_LOGON_FAILURE
167+
NS_E_WMP_UNSUPPORTED_FORMAT
168+
NS_E_WMP_URLDOWNLOADFAILED
155169
NTSTATUS
156170
OBJ_TYPE
157171
OBJECT_IDENTIFIER
158172
OffsetViewportOrgEx
159-
OLECMDERR_E_DISABLED
160-
OLECMDERR_E_NOTSUPPORTED
161-
OLECMDERR_E_UNKNOWNGROUP
162173
OLE_E_ADVISENOTSUPPORTED
163174
OLE_E_INVALIDRECT
164175
OLE_E_NOCONNECTION
165176
OLE_E_PROMPTSAVECANCELLED
177+
OLECMDERR_E_DISABLED
178+
OLECMDERR_E_NOTSUPPORTED
179+
OLECMDERR_E_UNKNOWNGROUP
166180
OleCreatePictureIndirect
181+
OleDuplicateData
182+
OleFlushClipboard
183+
OleGetClipboard
184+
OleInitialize
185+
OleSetClipboard
186+
OleUninitialize
167187
PeekMessage
168-
PostMessage
169188
POINTS
189+
PostMessage
170190
PRINTDLGEX_FLAGS
171191
PropVariantClear
172192
PWSTR
173193
RealizePalette
174194
RECT
175195
REGDB_E_CLASSNOTREG
176196
RegisterClipboardFormat
197+
RegisterDragDrop
177198
ReleaseDC
199+
ReleaseStgMedium
178200
RestoreDC
201+
RevokeDragDrop
179202
RPC_E_CHANGED_MODE
180203
RPC_E_DISCONNECTED
181204
RPC_E_SERVERFAULT
@@ -218,6 +241,7 @@ SystemParametersInfoForDpi
218241
TYPE_E_BADMODULEKIND
219242
UNICODE_STRING_MAX_CHARS
220243
VIEW_E_DRAW
244+
WideCharToMultiByte
221245
WIN32_ERROR
222246
WINCODEC_ERR_*
223247
WINDOW_LONG_PTR_INDEX
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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.Runtime.CompilerServices;
5+
using System.Runtime.Serialization.Formatters.Binary;
6+
7+
namespace System.Private.Windows;
8+
9+
// Borrowed from https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/LocalAppContextSwitches.Common.cs
10+
internal static class CoreAppContextSwitches
11+
{
12+
// Enabling switches in Core is different from Framework. See https://learn.microsoft.com/dotnet/core/runtime-config/
13+
// for details on how to set switches.
14+
internal const string ClipboardDragDropEnableUnsafeBinaryFormatterSerializationSwitchName = "Windows.ClipboardDragDrop.EnableUnsafeBinaryFormatterSerialization";
15+
internal const string ClipboardDragDropEnableNrbfSerializationSwitchName = "Windows.ClipboardDragDrop.EnableNrbfSerialization";
16+
17+
private static int s_clipboardDragDropEnableUnsafeBinaryFormatterSerialization;
18+
private static int s_clipboardDragDropEnableNrbfSerialization;
19+
20+
private static bool GetCachedSwitchValue(string switchName, ref int cachedSwitchValue)
21+
{
22+
// The cached switch value has 3 states: 0 - unknown, 1 - true, -1 - false
23+
if (cachedSwitchValue < 0)
24+
{
25+
return false;
26+
}
27+
28+
if (cachedSwitchValue > 0)
29+
{
30+
return true;
31+
}
32+
33+
return GetSwitchValue(switchName, ref cachedSwitchValue);
34+
}
35+
36+
private static bool GetSwitchValue(string switchName, ref int cachedSwitchValue)
37+
{
38+
bool hasSwitch = AppContext.TryGetSwitch(switchName, out bool isSwitchEnabled);
39+
if (!hasSwitch)
40+
{
41+
isSwitchEnabled = GetSwitchDefaultValue(switchName);
42+
}
43+
44+
AppContext.TryGetSwitch("TestSwitch.LocalAppContext.DisableCaching", out bool disableCaching);
45+
if (!disableCaching)
46+
{
47+
cachedSwitchValue = isSwitchEnabled ? 1 /*true*/ : -1 /*false*/;
48+
}
49+
else if (!hasSwitch)
50+
{
51+
AppContext.SetSwitch(switchName, isSwitchEnabled);
52+
}
53+
54+
return isSwitchEnabled;
55+
}
56+
57+
private static bool GetSwitchDefaultValue(string switchName)
58+
{
59+
if (switchName == ClipboardDragDropEnableNrbfSerializationSwitchName)
60+
{
61+
return true;
62+
}
63+
64+
return false;
65+
}
66+
67+
/// <summary>
68+
/// If <see langword="true"/>, then Clipboard and DataObject Get and Set methods will attempts to serialize or deserialize
69+
/// binary formatted content using either <see cref="BinaryFormatter"/> or System.Windows.Forms.BinaryFormat.Deserializer.
70+
/// To use <see cref="BinaryFormatter"/>, application should also opt in into the
71+
/// "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization" option and reference the out-of-band
72+
/// "System.Runtime.Serialization.Formatters" NuGet package and opt out from using the System.Windows.Forms.BinaryFormat.Deserializer
73+
/// by setting "Windows.ClipboardDragDrop.EnableNrbfSerialization" to <see langword="true"/>
74+
/// </summary>
75+
public static bool ClipboardDragDropEnableUnsafeBinaryFormatterSerialization
76+
{
77+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
78+
get => GetCachedSwitchValue(ClipboardDragDropEnableUnsafeBinaryFormatterSerializationSwitchName,
79+
ref s_clipboardDragDropEnableUnsafeBinaryFormatterSerialization);
80+
}
81+
82+
/// <summary>
83+
/// If <see langword="true"/>, then Clipboard Get methods will prefer System.Windows.Forms.BinaryFormat.Deserializer
84+
/// to deserialize the payload, if needed. If <see langword="false"/>, then <see cref="BinaryFormatter"/> is used
85+
/// to get full compatibility with the downlevel versions of .NET.
86+
/// </summary>
87+
/// <remarks>
88+
/// <para>
89+
/// This switch has no effect if "Windows.ClipboardDragDrop.EnableUnsafeBinaryFormatterSerialization"
90+
/// is set to <see langword="false"/>.
91+
/// </para>
92+
/// </remarks>
93+
public static bool ClipboardDragDropEnableNrbfSerialization
94+
{
95+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
96+
get => GetCachedSwitchValue(ClipboardDragDropEnableNrbfSerializationSwitchName, ref s_clipboardDragDropEnableNrbfSerialization);
97+
}
98+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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;
5+
6+
internal static class FeatureSwitches
7+
{
8+
// Feature switch, when set to false, BinaryFormatter is not supported in trimmed applications.
9+
// This field, using the default BinaryFormatter switch, is used to control trim warnings related
10+
// to using BinaryFormatter in WinForms trimming. The trimmer will generate a warning when set
11+
// to true and will not generate a warning when set to false.
12+
#if NET9_0_OR_GREATER
13+
[FeatureSwitchDefinition("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization")]
14+
#endif
15+
internal static bool EnableUnsafeBinaryFormatterInNativeObjectSerialization =>
16+
!AppContext.TryGetSwitch("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", out bool isEnabled)
17+
|| isEnabled;
18+
}

0 commit comments

Comments
 (0)