Skip to content

Commit 86616a8

Browse files
authored
Multi-target System.Private.Windows.Core (#14384)
This builds our shared functionality assembly for .NET Framework 4.7.2 as Microsoft.Private.Windows.Core with the same namespaces. This is for internal scenarios where we need this shared functionality on .NET Framework. Static and default interface methods don't work on .NET Framework. For our composition usages of static interfaces we build the same interface with instance methods and constrain the consuming types to `new()` as well so they can create a static instance of the `T` that they need. On Framework we still use direct COM to look at existing COM objects. For CCWs, however, we let `Marshal` provide them on Framework. Most of the complexity around that is with unwrapping DataObject. I believe things should work as expected but it is a particular focus point for both testing and following up with issues when utilizing this code. There are some CsWin32 tweaks that are necessary, notably around `IComIId`. Added partials for the COM classes where we needed them. Framework only code is in the `Framework` subfolder and ingested through the previously committed shared polyfill project. Some tests needed to be tweaked for a few reasons. One in particular was that some validated implementation details rather than functional. Some shared test functionality (notably validators that depend on static numeric interfaces) was simply excluded on .NET Framework as it wasn't being used in the tests that we needed to multitarget. .NET Framework versions can be added if/when needed.
1 parent f8ef19c commit 86616a8

110 files changed

Lines changed: 1451 additions & 341 deletions

File tree

Some content is hidden

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

Winforms.sln

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Private.Windows.P
214214
EndProject
215215
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Microsoft.Private.Windows.Polyfills", "src\Microsoft.Private.Windows.Polyfills\Microsoft.Private.Windows.Polyfills.shproj", "{799CC0C2-236B-4A76-8CE3-65C346182CC1}"
216216
EndProject
217+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Private.Windows.Core", "src\System.Private.Windows.Core\src\Microsoft.Private.Windows.Core.csproj", "{36A02BBB-B60B-5F23-6AF0-F41561A9275C}"
218+
EndProject
217219
Global
218220
GlobalSection(SolutionConfigurationPlatforms) = preSolution
219221
Debug|Any CPU = Debug|Any CPU
@@ -1082,6 +1084,22 @@ Global
10821084
{4A2BD741-482C-4BF7-8A2D-5535A770DB69}.Release|x64.Build.0 = Release|Any CPU
10831085
{4A2BD741-482C-4BF7-8A2D-5535A770DB69}.Release|x86.ActiveCfg = Release|Any CPU
10841086
{4A2BD741-482C-4BF7-8A2D-5535A770DB69}.Release|x86.Build.0 = Release|Any CPU
1087+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1088+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Debug|Any CPU.Build.0 = Debug|Any CPU
1089+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Debug|arm64.ActiveCfg = Debug|Any CPU
1090+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Debug|arm64.Build.0 = Debug|Any CPU
1091+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Debug|x64.ActiveCfg = Debug|Any CPU
1092+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Debug|x64.Build.0 = Debug|Any CPU
1093+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Debug|x86.ActiveCfg = Debug|Any CPU
1094+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Debug|x86.Build.0 = Debug|Any CPU
1095+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Release|Any CPU.ActiveCfg = Release|Any CPU
1096+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Release|Any CPU.Build.0 = Release|Any CPU
1097+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Release|arm64.ActiveCfg = Release|Any CPU
1098+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Release|arm64.Build.0 = Release|Any CPU
1099+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Release|x64.ActiveCfg = Release|Any CPU
1100+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Release|x64.Build.0 = Release|Any CPU
1101+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Release|x86.ActiveCfg = Release|Any CPU
1102+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C}.Release|x86.Build.0 = Release|Any CPU
10851103
EndGlobalSection
10861104
GlobalSection(SolutionProperties) = preSolution
10871105
HideSolutionNode = FALSE
@@ -1150,11 +1168,13 @@ Global
11501168
{7BFA3A16-A19A-4FCE-AE1E-D1187BD92D4C} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
11511169
{4A2BD741-482C-4BF7-8A2D-5535A770DB69} = {583F1292-AE8D-4511-B8D8-A81FE4642DDC}
11521170
{799CC0C2-236B-4A76-8CE3-65C346182CC1} = {77FEDB47-F7F6-490D-AF7C-ABB4A9E0B9D7}
1171+
{36A02BBB-B60B-5F23-6AF0-F41561A9275C} = {77FEDB47-F7F6-490D-AF7C-ABB4A9E0B9D7}
11531172
EndGlobalSection
11541173
GlobalSection(ExtensibilityGlobals) = postSolution
11551174
SolutionGuid = {7B1B0433-F612-4E5A-BE7E-FCF5B9F6E136}
11561175
EndGlobalSection
11571176
GlobalSection(SharedMSBuildProjectFiles) = preSolution
1177+
src\Microsoft.Private.Windows.Polyfills\Microsoft.Private.Windows.Polyfills.projitems*{36a02bbb-b60b-5f23-6af0-f41561a9275c}*SharedItemsImports = 5
11581178
src\Microsoft.Private.Windows.Polyfills\Microsoft.Private.Windows.Polyfills.projitems*{799cc0c2-236b-4a76-8ce3-65c346182cc1}*SharedItemsImports = 13
11591179
EndGlobalSection
11601180
EndGlobal

src/Common/tests/TestUtilities/BinaryFormatterInClipboardDragDropScope.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ public BinaryFormatterInClipboardDragDropScope(bool enable)
1414
AppContextSwitchNames.ClipboardDragDropEnableUnsafeBinaryFormatterSerializationSwitchName,
1515
() => AppContextSwitchScope.GetDefaultValueForSwitchInAssembly(
1616
AppContextSwitchNames.ClipboardDragDropEnableUnsafeBinaryFormatterSerializationSwitchName,
17+
#if NET
1718
"System.Private.Windows.Core",
19+
#else
20+
"Microsoft.Private.Windows.Core",
21+
#endif
1822
"System.Private.Windows.CoreAppContextSwitches"),
1923
enable);
2024
}

src/Common/tests/TestUtilities/BinaryFormatterScope.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public BinaryFormatterScope(bool enable)
1717
// Prevent multiple BinaryFormatterScopes from running simultaneously. Using Monitor to allow recursion on
1818
// the same thread.
1919
Monitor.Enter(typeof(BinaryFormatterScope));
20-
_switchScope = new(AppContextSwitchNames.EnableUnsafeBinaryFormatterSerialization, GetDefaultValue, enable);
20+
_switchScope = new(AppContextSwitchNames.EnableUnsafeBinaryFormatterSerialization, () => false, enable);
2121
}
2222

2323
public void Dispose()
@@ -31,6 +31,4 @@ public void Dispose()
3131
Monitor.Exit(typeof(BinaryFormatterScope));
3232
}
3333
}
34-
35-
public static bool GetDefaultValue() => false;
3634
}

src/Common/tests/TestUtilities/BinarySerialization.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33

44
using System.Formats.Nrbf;
55
using System.Reflection;
6-
using System.Runtime.CompilerServices;
76
using System.Runtime.Serialization;
87
using System.Runtime.Serialization.Formatters;
98
using System.Runtime.Serialization.Formatters.Binary;
109

10+
#if NET
11+
using System.Runtime.CompilerServices;
12+
#endif
13+
1114
namespace System;
1215

1316
public static class BinarySerialization

src/Common/tests/TestUtilities/CommonTestHelper.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ public static TheoryData<char> GetCharTheoryData()
5151
public static TheoryData<IntPtr> GetIntPtrTheoryData()
5252
=> new()
5353
{
54-
-1,
54+
(nint)(-1),
5555
IntPtr.Zero,
56-
1
56+
(nint)1
5757
};
5858

5959
public static TheoryData<Color> GetColorTheoryData()

src/Common/tests/TestUtilities/ComparisonHelpers.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
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+
#if NET
45
using System.Numerics;
56

67
namespace System;
@@ -110,3 +111,4 @@ public static bool EqualsFloating<T>(T x, T y, T variance)
110111
static unsafe bool IsPositiveZero(T value) => T.IsZero(value) && T.IsPositive(value);
111112
}
112113
}
114+
#endif

src/Common/tests/TestUtilities/FluentAssertions/FluentAssertExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Drawing;
5+
#if NET
56
using FluentAssertions.Collections;
7+
#endif
68
using FluentAssertions.Execution;
79
using FluentAssertions.Numeric;
810
using FluentAssertions.Primitives;
@@ -43,6 +45,7 @@ public static AndConstraint<RectangleFAssertions> BeApproximately(
4345
return new(parent);
4446
}
4547

48+
#if NET
4649
/// <summary>
4750
/// Asserts that two <see cref="RectangleF"/> collections contain the same items in the same order
4851
/// within the given <paramref name="precision"/>.
@@ -63,6 +66,7 @@ public static AndConstraint<GenericCollectionAssertions<RectangleF>> BeApproxima
6366
&& ComparisonHelpers.EqualsFloating(expected.Height, actual.Height, precision),
6467
because,
6568
becauseArgs);
69+
#endif
6670

6771
/// <summary>
6872
/// Asserts a <see cref="PointF"/> value approximates another value as close as possible.
@@ -82,6 +86,7 @@ public static AndConstraint<PointFAssertions> BeApproximately(
8286
return new AndConstraint<PointFAssertions>(parent);
8387
}
8488

89+
#if NET
8590
/// <summary>
8691
/// Asserts that two <see cref="PointF"/> collections contain the same items in the same order
8792
/// within the given <paramref name="precision"/>.
@@ -100,6 +105,7 @@ public static AndConstraint<GenericCollectionAssertions<PointF>> BeApproximately
100105
&& ComparisonHelpers.EqualsFloating(expected.Y, actual.Y, precision),
101106
because,
102107
becauseArgs);
108+
#endif
103109

104110
/// <summary>
105111
/// Asserts a <see cref="Rectangle"/> is empty.
Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,39 @@
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.Runtime.CompilerServices;
5-
64
namespace System;
75

86
internal static class ModuleInitializer
97
{
10-
[ModuleInitializer]
8+
#if NET
9+
[Runtime.CompilerServices.ModuleInitializer]
10+
#endif
1111
[SuppressMessage("Usage", "CA2255:The 'ModuleInitializer' attribute should not be used in libraries", Justification = "Intentional use of module initializer to register trace listener.")]
1212
internal static void Initialize()
1313
{
1414
Trace.Listeners.Clear();
1515
Trace.Listeners.Add(ThrowingTraceListener.Instance);
1616
}
17+
18+
#if NETFRAMEWORK
19+
private static bool s_initialized;
20+
private static readonly object s_lock = new object();
21+
22+
internal static void EnsureInitialized()
23+
{
24+
if (!s_initialized)
25+
{
26+
lock (s_lock)
27+
{
28+
if (s_initialized)
29+
{
30+
return;
31+
}
32+
33+
Initialize();
34+
s_initialized = true;
35+
}
36+
}
37+
}
38+
#endif
1739
}

src/Common/tests/TestUtilities/NoAssertContext.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ public sealed class NoAssertContext : IDisposable
1818
// We do, however need to lock around hooking/unhooking our custom listener to make sure that we
1919
// are rerouting correctly if multiple threads are creating/disposing this class concurrently.
2020

21+
#if NET
2122
private static readonly Lock s_lock = new();
23+
#else
24+
private static readonly object s_lock = new();
25+
#endif
26+
2227
private static bool s_hooked;
2328
private static bool s_hasDefaultListener;
2429
private static bool s_hasThrowingListener;
@@ -31,6 +36,10 @@ public sealed class NoAssertContext : IDisposable
3136

3237
public NoAssertContext()
3338
{
39+
#if NETFRAMEWORK
40+
ModuleInitializer.EnsureInitialized();
41+
#endif
42+
3443
s_suppressedThreads.AddOrUpdate(Environment.CurrentManagedThreadId, 1, (key, oldValue) => oldValue + 1);
3544

3645
// Lock to make sure we are hooked properly if two threads come into the constructor/dispose at the same time.

src/Common/tests/TestUtilities/NrbfSerializerInClipboardDragDropScope.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ public NrbfSerializerInClipboardDragDropScope(bool enable)
1414
AppContextSwitchNames.ClipboardDragDropEnableNrbfSerializationSwitchName,
1515
() => AppContextSwitchScope.GetDefaultValueForSwitchInAssembly(
1616
AppContextSwitchNames.ClipboardDragDropEnableNrbfSerializationSwitchName,
17+
#if NET
1718
"System.Private.Windows.Core",
19+
#else
20+
"Microsoft.Private.Windows.Core",
21+
#endif
1822
"System.Private.Windows.CoreAppContextSwitches"),
1923
enable);
2024
}

0 commit comments

Comments
 (0)