diff --git a/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml b/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml index f18022997..892d6d680 100644 --- a/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml +++ b/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml @@ -5,7 +5,7 @@ stages: - job: BuildAndTest pool: vmImage: windows-latest - timeoutInMinutes: 90 + timeoutInMinutes: 120 # https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration strategy: maxParallel: 10 @@ -113,6 +113,16 @@ stages: _build\$(BuildPlatform)\$(BuildConfiguration)\AuthoringConsumptionTest\bin\AuthoringConsumptionTest.exe --gtest_output=xml:AUTHORINGTEST-$(Build.BuildNumber).xml exit /b 0 +# Run Functional Tests + - task: CmdLine@2 + displayName: Run Functional Tests + condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'))) + inputs: + workingDirectory: $(Build.SourcesDirectory)\src + script: | + set cswinrt_label=functionaltest + build.cmd $(BuildPlatform) $(BuildConfiguration) $(VersionNumber) $(Build.BuildNumber) $(WinRT.Runtime.AssemblyVersion) + - job: Benchmarks displayName: Run Benchmarks condition: or(eq(variables['_RunBenchmarks'],'true'), eq(variables['Build.Reason'],'Schedule')) diff --git a/src/Perf/IIDOptimizer/SignatureGenerator.cs b/src/Perf/IIDOptimizer/SignatureGenerator.cs index d184c6215..7c9271254 100644 --- a/src/Perf/IIDOptimizer/SignatureGenerator.cs +++ b/src/Perf/IIDOptimizer/SignatureGenerator.cs @@ -201,6 +201,12 @@ bool TryGetDefaultInterfaceTypeForRuntimeClassType(TypeReference runtimeClassTyp return false; } + if (runtimeClassAttribute.ConstructorArguments[0].Value is TypeReference typeReference) + { + defaultInterface = typeReference; + return true; + } + string defaultInterfacePropertyName = (string)runtimeClassAttribute.ConstructorArguments[0].Value; var defaultInterfaceProperty = rcDef.Properties.FirstOrDefault(prop => prop.Name == defaultInterfacePropertyName); diff --git a/src/Projections/Reunion/Reunion.csproj b/src/Projections/Reunion/Reunion.csproj index 0cff1b9ef..aedc6b79a 100644 --- a/src/Projections/Reunion/Reunion.csproj +++ b/src/Projections/Reunion/Reunion.csproj @@ -5,6 +5,8 @@ x64;x86 Microsoft.WinUI 9.9.9.9 + true + true diff --git a/src/Projections/Test/Test.csproj b/src/Projections/Test/Test.csproj index 4ae22502c..b72f2d496 100644 --- a/src/Projections/Test/Test.csproj +++ b/src/Projections/Test/Test.csproj @@ -3,6 +3,8 @@ netstandard2.0;net5.0;net6.0 x64;x86 + true + true diff --git a/src/Projections/Test/TestHost.ProbeByHost.cs b/src/Projections/Test/TestHost.ProbeByHost.cs index f8b6d8a0d..ba95df96e 100644 --- a/src/Projections/Test/TestHost.ProbeByHost.cs +++ b/src/Projections/Test/TestHost.ProbeByHost.cs @@ -12,7 +12,8 @@ namespace Windows.Foundation { [global::WinRT.WindowsRuntimeType] - [Guid("00000035-0000-0000-c000-000000000046")] + [Guid("00000035-0000-0000-c000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.Windows.Foundation.IActivationFactory))] internal interface IActivationFactory { Object ActivateInstance(); diff --git a/src/Projections/TestHost.ProbeByClass/TestHost.ProbeByClass.cs b/src/Projections/TestHost.ProbeByClass/TestHost.ProbeByClass.cs index f2eebbb6b..c6078c042 100644 --- a/src/Projections/TestHost.ProbeByClass/TestHost.ProbeByClass.cs +++ b/src/Projections/TestHost.ProbeByClass/TestHost.ProbeByClass.cs @@ -12,7 +12,8 @@ namespace Windows.Foundation { [global::WinRT.WindowsRuntimeType] - [Guid("00000035-0000-0000-c000-000000000046")] + [Guid("00000035-0000-0000-c000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.Windows.Foundation.IActivationFactory))] internal interface IActivationFactory { Object ActivateInstance(); diff --git a/src/Projections/WinUI/WinUI.csproj b/src/Projections/WinUI/WinUI.csproj index bdadc3a37..a018f36ed 100644 --- a/src/Projections/WinUI/WinUI.csproj +++ b/src/Projections/WinUI/WinUI.csproj @@ -3,6 +3,8 @@ netstandard2.0;net5.0;net6.0 x64;x86 + true + true diff --git a/src/Projections/Windows/Windows.csproj b/src/Projections/Windows/Windows.csproj index 7311ac284..825ddc72e 100644 --- a/src/Projections/Windows/Windows.csproj +++ b/src/Projections/Windows/Windows.csproj @@ -4,6 +4,8 @@ netstandard2.0;net5.0;net6.0 x64;x86 Microsoft.Windows.SDK.NET + true + true diff --git a/src/Tests/FunctionalTests/Async/Async.csproj b/src/Tests/FunctionalTests/Async/Async.csproj new file mode 100644 index 000000000..43370b531 --- /dev/null +++ b/src/Tests/FunctionalTests/Async/Async.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/FunctionalTests/Async/Program.cs b/src/Tests/FunctionalTests/Async/Program.cs new file mode 100644 index 000000000..b43cc2c89 --- /dev/null +++ b/src/Tests/FunctionalTests/Async/Program.cs @@ -0,0 +1,65 @@ +using System; +using System.Threading.Tasks; +using TestComponentCSharp; + +var instance = new Class(); + +instance.IntProperty = 12; +var async_get_int = instance.GetIntAsync(); +int async_int = 0; +async_get_int.Completed = (info, status) => async_int = info.GetResults(); +async_get_int.GetResults(); + +if (async_int != 12) +{ + return 101; +} + +instance.StringProperty = "foo"; +var async_get_string = instance.GetStringAsync(); +string async_string = ""; +async_get_string.Completed = (info, status) => async_string = info.GetResults(); +int async_progress; +async_get_string.Progress = (info, progress) => async_progress = progress; +async_get_string.GetResults(); + +if (async_string != "foo") +{ + return 102; +} + +var task = InvokeAddAsync(instance, 20, 10); +if (task.Wait(25)) +{ + return 103; +} + +instance.CompleteAsync(); +if (!task.Wait(1000)) +{ + return 104; +} + +if (task.Status != TaskStatus.RanToCompletion || task.Result != 30) +{ + return 105; +} + +var ports = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync( + Windows.Devices.SerialCommunication.SerialDevice.GetDeviceSelector(), + new string[] { "System.ItemNameDisplay" }); +foreach (var port in ports) +{ + object o = port.Properties["System.ItemNameDisplay"]; + if (o is null) + { + return 106; + } +} + +return 100; + +static async Task InvokeAddAsync(Class instance, int lhs, int rhs) +{ + return await instance.AddAsync(lhs, rhs); +} \ No newline at end of file diff --git a/src/Tests/FunctionalTests/CCW/CCW.csproj b/src/Tests/FunctionalTests/CCW/CCW.csproj new file mode 100644 index 000000000..481703f07 --- /dev/null +++ b/src/Tests/FunctionalTests/CCW/CCW.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + \ No newline at end of file diff --git a/src/Tests/FunctionalTests/CCW/Program.cs b/src/Tests/FunctionalTests/CCW/Program.cs new file mode 100644 index 000000000..f436a2da1 --- /dev/null +++ b/src/Tests/FunctionalTests/CCW/Program.cs @@ -0,0 +1,80 @@ +using System; +using TestComponentCSharp; +using WinRT.Interop; +using WinRT; + +var managedProperties = new ManagedProperties(42); +var instance = new Class(); + +// Ensure we can use the IProperties interface from the native side. +instance.CopyProperties(managedProperties); +if (managedProperties.ReadWriteProperty != instance.ReadWriteProperty) +{ + return 101; +} + +// Check for the default interfaces provided by WinRT.Runtime +Guid IID_IMarshal = new Guid("00000003-0000-0000-c000-000000000046"); +IObjectReference ccw = MarshalInterface.CreateMarshaler(managedProperties); +ccw.TryAs(IID_IMarshal, out var marshalCCW); +if (marshalCCW == null) +{ + return 102; +} + +// Check for managed implemented interface to ensure not trimmed. +Guid IID_IUriHandler = new Guid("FF4B4334-2104-537D-812E-67E3856AC7A2"); +ccw.TryAs(IID_IUriHandler, out var uriHandlerCCW); +if (uriHandlerCCW == null) +{ + return 103; +} + +// Ensure that interfaces on the vtable / object don't get trimmed even if unused. +Guid IID_IWarning1 = new Guid("4DB3FA26-4BB1-50EA-8362-98F49651E516"); +Guid IID_IWarningClassOverrides = new Guid("E5635CE4-D483-55AA-86D5-080DC07F0A09"); + +var managedWarningClass = new ManagedWarningClass(); +ccw = MarshalInterface.CreateMarshaler(managedWarningClass); +ccw.TryAs(IID_IWarning1, out var warningCCW); +if (warningCCW == null) +{ + return 104; +} + +ccw.TryAs(IID_IWarningClassOverrides, out var warningOverrideCCW); +if (warningOverrideCCW == null) +{ + return 105; +} + +return 100; + +sealed class ManagedProperties : IProperties1, IUriHandler +{ + private readonly int _value; + + public ManagedProperties(int value) + { + _value = value; + } + + public int ReadWriteProperty => _value; + + public void AddUriHandler(ProvideUri provideUri) + { + _ = provideUri(); + } + + void IUriHandler.AddUriHandler(ProvideUri provideUri) => AddUriHandler(provideUri); +} + +sealed class ManagedWarningClass : WarningClass, IUriHandler +{ + public void AddUriHandler(ProvideUri provideUri) + { + _ = provideUri(); + } + + void IUriHandler.AddUriHandler(ProvideUri provideUri) => AddUriHandler(provideUri); +} \ No newline at end of file diff --git a/src/Tests/FunctionalTests/ClassActivation/ClassActivation.csproj b/src/Tests/FunctionalTests/ClassActivation/ClassActivation.csproj new file mode 100644 index 000000000..43370b531 --- /dev/null +++ b/src/Tests/FunctionalTests/ClassActivation/ClassActivation.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/FunctionalTests/ClassActivation/Program.cs b/src/Tests/FunctionalTests/ClassActivation/Program.cs new file mode 100644 index 000000000..efa64e53f --- /dev/null +++ b/src/Tests/FunctionalTests/ClassActivation/Program.cs @@ -0,0 +1,18 @@ +using System; +using TestComponentCSharp; + +// new RCW / Factory activation +var instance = new Class(); + +var expectedEnum = EnumValue.Two; +instance.EnumProperty = expectedEnum; + +// Custom type marshaling +var expectedUri = new Uri("http://expected"); +instance.UriProperty = expectedUri; + +var instance2 = new Class(32); + +return instance.EnumProperty == expectedEnum && + instance.UriProperty == expectedUri && + instance2.IntProperty == 32 ? 100 : 101; diff --git a/src/Tests/FunctionalTests/Collections/Collections.csproj b/src/Tests/FunctionalTests/Collections/Collections.csproj new file mode 100644 index 000000000..43370b531 --- /dev/null +++ b/src/Tests/FunctionalTests/Collections/Collections.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/FunctionalTests/Collections/Program.cs b/src/Tests/FunctionalTests/Collections/Program.cs new file mode 100644 index 000000000..cba570661 --- /dev/null +++ b/src/Tests/FunctionalTests/Collections/Program.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using System.Linq; +using test_component_derived.Nested; +using TestComponentCSharp; + +var instance = new Class(); + +var expected = new int[] { 0, 1, 2 }; + +instance.BindableIterableProperty = expected; +if (expected != instance.BindableIterableProperty) +{ + return 101; +} + +var instance2 = TestComponent.TestRunner.MakeTests(); +var dict = new Dictionary() +{ + ["apples"] = "1", + ["oranges"] = "2", + ["pears"] = "3" +}; +IDictionary outDict = null; +var retDict = instance2.Collection3(dict, out outDict); +if (!SequencesEqual(dict, outDict, retDict)) +{ + return 101; +} + +float[] floatArr = new float[] { 1.0f, 2.0f, 3.0f }; +float[] floatArr2 = new float[floatArr.Length]; +float[] outFloatArr; +float[] retFloatArr = instance2.Array9(floatArr, floatArr2, out outFloatArr); +if (!AllEqual(floatArr, floatArr2, outFloatArr, retFloatArr)) +{ + return 101; +} + +var hierarchyDAsObjectList = HierarchyC.CreateDerivedHierarchyDAsObjectList(); +foreach (var hierarchyDAsObject in hierarchyDAsObjectList) +{ + var hierarchyDAsHierarchyCCast = (HierarchyC)hierarchyDAsObject; + if (hierarchyDAsHierarchyCCast.HierarchyB_Method() != "HierarchyC.HierarchyB_Method" || + hierarchyDAsHierarchyCCast.HierarchyA_Method() != "HierarchyB.HierarchyA_Method") + { + return 101; + } +} + +var hierarchyDAsHierarchyCList = HierarchyC.CreateDerivedHierarchyDList(); +foreach (var hierarchyDAsHierarchyC in hierarchyDAsHierarchyCList) +{ + if (hierarchyDAsHierarchyC.HierarchyB_Method() != "HierarchyC.HierarchyB_Method" || + hierarchyDAsHierarchyC.HierarchyA_Method() != "HierarchyB.HierarchyA_Method") + { + return 101; + } +} + +return 100; + +static bool SequencesEqual(IEnumerable x, params IEnumerable[] list) => list.All((y) => x.SequenceEqual(y)); + +static bool AllEqual(T[] x, params T[][] list) => list.All((y) => x.SequenceEqual(y)); diff --git a/src/Tests/FunctionalTests/DerivedClassActivation/DerivedClassActivation.csproj b/src/Tests/FunctionalTests/DerivedClassActivation/DerivedClassActivation.csproj new file mode 100644 index 000000000..43370b531 --- /dev/null +++ b/src/Tests/FunctionalTests/DerivedClassActivation/DerivedClassActivation.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/FunctionalTests/DerivedClassActivation/Program.cs b/src/Tests/FunctionalTests/DerivedClassActivation/Program.cs new file mode 100644 index 000000000..9e49d265b --- /dev/null +++ b/src/Tests/FunctionalTests/DerivedClassActivation/Program.cs @@ -0,0 +1,6 @@ +using test_component_base; +using test_component_derived.Nested; + +HierarchyB hierarchyCAsHierarchyB = new HierarchyC(); +return hierarchyCAsHierarchyB.HierarchyB_Method() == "HierarchyC.HierarchyB_Method" && + hierarchyCAsHierarchyB.HierarchyA_Method() == "HierarchyB.HierarchyA_Method" ? 100 : 101; diff --git a/src/Tests/FunctionalTests/DerivedClassAsBaseClass/DerivedClassAsBaseClass.csproj b/src/Tests/FunctionalTests/DerivedClassAsBaseClass/DerivedClassAsBaseClass.csproj new file mode 100644 index 000000000..43370b531 --- /dev/null +++ b/src/Tests/FunctionalTests/DerivedClassAsBaseClass/DerivedClassAsBaseClass.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/FunctionalTests/DerivedClassAsBaseClass/Program.cs b/src/Tests/FunctionalTests/DerivedClassAsBaseClass/Program.cs new file mode 100644 index 000000000..af9dfdd3c --- /dev/null +++ b/src/Tests/FunctionalTests/DerivedClassAsBaseClass/Program.cs @@ -0,0 +1,18 @@ +using test_component_base; +using test_component_derived.Nested; + +var hierarchyDAsHierarchyC = HierarchyC.CreateDerivedHierarchyD(); +if (hierarchyDAsHierarchyC.HierarchyB_Method() != "HierarchyC.HierarchyB_Method" || + hierarchyDAsHierarchyC.HierarchyA_Method() != "HierarchyB.HierarchyA_Method") +{ + return 101; +} + +var hierarchyDAsHierarchyCCast = (HierarchyC) HierarchyC.CreateDerivedHierarchyDAsObject(); +if (hierarchyDAsHierarchyCCast.HierarchyB_Method() != "HierarchyC.HierarchyB_Method" || + hierarchyDAsHierarchyCCast.HierarchyA_Method() != "HierarchyB.HierarchyA_Method") +{ + return 101; +} + +return 100; \ No newline at end of file diff --git a/src/Tests/FunctionalTests/DynamicInterfaceCasting/DynamicInterfaceCasting.csproj b/src/Tests/FunctionalTests/DynamicInterfaceCasting/DynamicInterfaceCasting.csproj new file mode 100644 index 000000000..43370b531 --- /dev/null +++ b/src/Tests/FunctionalTests/DynamicInterfaceCasting/DynamicInterfaceCasting.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/FunctionalTests/DynamicInterfaceCasting/Program.cs b/src/Tests/FunctionalTests/DynamicInterfaceCasting/Program.cs new file mode 100644 index 000000000..dcbb8323f --- /dev/null +++ b/src/Tests/FunctionalTests/DynamicInterfaceCasting/Program.cs @@ -0,0 +1,7 @@ +using TestComponent; +using WinRT; +using WinRT.Interop; + +var instance = new Class(); +var agileObject = (IAgileObject)(IWinRTObject)instance; +return agileObject != null ? 100 : 101; \ No newline at end of file diff --git a/src/Tests/FunctionalTests/Events/Events.csproj b/src/Tests/FunctionalTests/Events/Events.csproj new file mode 100644 index 000000000..43370b531 --- /dev/null +++ b/src/Tests/FunctionalTests/Events/Events.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/FunctionalTests/Events/Program.cs b/src/Tests/FunctionalTests/Events/Program.cs new file mode 100644 index 000000000..f798035a8 --- /dev/null +++ b/src/Tests/FunctionalTests/Events/Program.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TestComponentCSharp; + +int events_expected = 0; +int events_received = 0; + +var instance = new Class(); + +instance.Event0 += () => events_received++; +instance.InvokeEvent0(); +events_expected++; + +instance.Event1 += (Class sender) => +{ + events_received++; +}; +instance.InvokeEvent1(instance); +events_expected++; + +int int0 = 42; +instance.Event2 += (Class sender, int arg0) => +{ + if (arg0 == int0) + { + events_received++; + } +}; +instance.InvokeEvent2(instance, int0); +events_expected++; + +var collection0 = new int[] { 42, 1729 }; +var collection1 = new Dictionary { [1] = "foo", [2] = "bar" }; +instance.CollectionEvent += (Class sender, IList arg0, IDictionary arg1) => +{ + if (arg0.SequenceEqual(collection0) && arg1.SequenceEqual(collection1)) + { + events_received++; + } +}; +instance.InvokeCollectionEvent(instance, collection0, collection1); +events_expected++; + +var managedUriHandler = new ManagedUriHandler(); +instance.AddUriHandler(managedUriHandler); +bool uriMatches = managedUriHandler.Uri == new Uri("http://github.com"); + +return events_received == events_expected && uriMatches ? 100 : 101; + +class ManagedUriHandler : IUriHandler +{ + public Uri Uri { get; private set; } + + public void AddUriHandler(ProvideUri provideUri) + { + Uri = provideUri(); + } +} \ No newline at end of file diff --git a/src/Tests/FunctionalTests/JsonValueFunctionCalls/JsonValueFunctionCalls.csproj b/src/Tests/FunctionalTests/JsonValueFunctionCalls/JsonValueFunctionCalls.csproj new file mode 100644 index 000000000..ddd828fa9 --- /dev/null +++ b/src/Tests/FunctionalTests/JsonValueFunctionCalls/JsonValueFunctionCalls.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/FunctionalTests/JsonValueFunctionCalls/Program.cs b/src/Tests/FunctionalTests/JsonValueFunctionCalls/Program.cs new file mode 100644 index 000000000..1800a57ea --- /dev/null +++ b/src/Tests/FunctionalTests/JsonValueFunctionCalls/Program.cs @@ -0,0 +1,21 @@ +using Windows.Foundation; + +// Static function calls and create RCW for existing object. +IStringable[] a = new IStringable[] { + Windows.Data.Json.JsonValue.CreateNumberValue(3), + Windows.Data.Json.JsonValue.CreateNumberValue(4), + Windows.Data.Json.JsonValue.CreateNumberValue(5.0) + }; + +int result = 0; + +// Interface function call +foreach (var str in a) +{ + result += int.Parse(str.ToString()); +} + +// Class function call +result += (int)(a[1] as Windows.Data.Json.JsonValue).GetNumber(); + +return result == 16 ? 100 : 101; \ No newline at end of file diff --git a/src/Tests/FunctionalTests/PublishProfiles/win10-arm64.pubxml b/src/Tests/FunctionalTests/PublishProfiles/win10-arm64.pubxml new file mode 100644 index 000000000..5957dcb09 --- /dev/null +++ b/src/Tests/FunctionalTests/PublishProfiles/win10-arm64.pubxml @@ -0,0 +1,14 @@ + + + + FileSystem + arm64 + win10-arm64 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + True + False + False + True + true + + diff --git a/src/Tests/FunctionalTests/PublishProfiles/win10-x64.pubxml b/src/Tests/FunctionalTests/PublishProfiles/win10-x64.pubxml new file mode 100644 index 000000000..0e6acfc89 --- /dev/null +++ b/src/Tests/FunctionalTests/PublishProfiles/win10-x64.pubxml @@ -0,0 +1,14 @@ + + + + FileSystem + x64 + win10-x64 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + True + False + False + True + true + + diff --git a/src/Tests/FunctionalTests/PublishProfiles/win10-x86.pubxml b/src/Tests/FunctionalTests/PublishProfiles/win10-x86.pubxml new file mode 100644 index 000000000..ab39fc15f --- /dev/null +++ b/src/Tests/FunctionalTests/PublishProfiles/win10-x86.pubxml @@ -0,0 +1,14 @@ + + + + FileSystem + x86 + win10-x86 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + True + False + False + True + true + + diff --git a/src/Tests/FunctionalTests/Structs/Program.cs b/src/Tests/FunctionalTests/Structs/Program.cs new file mode 100644 index 000000000..1988ec481 --- /dev/null +++ b/src/Tests/FunctionalTests/Structs/Program.cs @@ -0,0 +1,22 @@ +using TestComponentCSharp; + +var instance = new Class(); +var blittable = instance.GetBlittableStructVector(); + +int sum = 0; +int expected_sum = 0; +for (int i = 0; i < blittable.Count; i++) +{ + sum += blittable[i].blittable.i32; + expected_sum += i; +} + +var nonblittable = instance.GetNonBlittableStructVector(); +for (int i = 0; i < nonblittable.Count; i++) +{ + sum += nonblittable[i].blittable.i32; + expected_sum += i; +} + +return sum == expected_sum ? 100 : 101; + diff --git a/src/Tests/FunctionalTests/Structs/Structs.csproj b/src/Tests/FunctionalTests/Structs/Structs.csproj new file mode 100644 index 000000000..43370b531 --- /dev/null +++ b/src/Tests/FunctionalTests/Structs/Structs.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + x86;x64 + win10-x86;win10-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win10-$(Platform).pubxml + true + false + + + + + + + + diff --git a/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj b/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj index b4d5d8a52..d014d2c83 100644 --- a/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj +++ b/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj @@ -47,6 +47,9 @@ Unicode false + + true + diff --git a/src/WinRT.Runtime/Attributes.cs b/src/WinRT.Runtime/Attributes.cs index 2a842db78..4599de3f3 100644 --- a/src/WinRT.Runtime/Attributes.cs +++ b/src/WinRT.Runtime/Attributes.cs @@ -3,6 +3,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace WinRT { @@ -64,5 +65,37 @@ public WindowsRuntimeTypeAttribute(string sourceMetadata = null) } public string SourceMetadata { get; } + } + + /// + /// When applied to a type, it specifies the provided type, if one is provided, is the ABI helper type for this type. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Delegate | AttributeTargets.Struct | AttributeTargets.Enum, Inherited = false, AllowMultiple = false)] +#if EMBED + internal +#else + public +#endif + sealed class WindowsRuntimeHelperTypeAttribute : Attribute + { + // Indicates no associated helper types (i.e. blittable types). + public WindowsRuntimeHelperTypeAttribute() + { + } + + public WindowsRuntimeHelperTypeAttribute( +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + Type helperType) + { + HelperType = helperType; + } + +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + public Type HelperType { get; } } } diff --git a/src/WinRT.Runtime/ComWrappersSupport.cs b/src/WinRT.Runtime/ComWrappersSupport.cs index bb9a3ece7..1ab7f18b4 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -149,7 +150,9 @@ public static ObjectReference GetObjectReferenceForInterface(IntPtr extern } } - public static void RegisterProjectionAssembly(Assembly assembly) => TypeNameSupport.RegisterProjectionAssembly(assembly); + public static void RegisterProjectionAssembly(Assembly assembly) => TypeNameSupport.RegisterProjectionAssembly(assembly); + + public static void RegisterProjectionTypeBaseTypeMapping(IDictionary typeNameToBaseTypeNameMapping) => TypeNameSupport.RegisterProjectionTypeBaseTypeMapping(typeNameToBaseTypeNameMapping); internal static object GetRuntimeClassCCWTypeIfAny(object obj) { @@ -166,7 +169,13 @@ internal static object GetRuntimeClassCCWTypeIfAny(object obj) return obj; } - internal static List GetInterfaceTableEntries(Type type) + internal static List GetInterfaceTableEntries( +#if NET6_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#elif NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] +#endif + Type type) { var entries = new List(); bool hasCustomIMarshalInterface = false; @@ -374,7 +383,11 @@ private static Func CreateNullableTFactory(Type implementa return (IInspectable obj) => getValueMethod.Invoke(null, new[] { obj }); } - private static Func CreateAbiNullableTFactory(Type implementationType) + private static Func CreateAbiNullableTFactory( +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] +#endif + Type implementationType) { var getValueMethod = implementationType.GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic); return (IInspectable obj) => getValueMethod.Invoke(null, new[] { obj }); @@ -413,7 +426,12 @@ private static Func CreateCustomTypeMappingFactory(Type cu return (IInspectable obj) => fromAbiMethodFunc(obj.ThisPtr); } - internal static Func CreateTypedRcwFactory(Type implementationType, string runtimeClassName = null) + internal static Func CreateTypedRcwFactory( +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif + Type implementationType, + string runtimeClassName = null) { // If runtime class name is empty or "Object", then just use IInspectable. if (implementationType == null || implementationType == typeof(object)) @@ -464,15 +482,18 @@ internal static Func CreateTypedRcwFactory(Type implementa } return CreateFactoryForImplementationType(runtimeClassName, implementationType); - } - + } + +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif internal static Type GetRuntimeClassForTypeCreation(IInspectable inspectable, Type staticallyDeterminedType) { string runtimeClassName = inspectable.GetRuntimeClassName(noThrow: true); Type implementationType = null; if (!string.IsNullOrEmpty(runtimeClassName)) { - implementationType = TypeNameSupport.FindTypeByNameCached(runtimeClassName); + implementationType = TypeNameSupport.FindRcwTypeByNameCached(runtimeClassName); } if (staticallyDeterminedType != null && staticallyDeterminedType != typeof(object)) diff --git a/src/WinRT.Runtime/ComWrappersSupport.net5.cs b/src/WinRT.Runtime/ComWrappersSupport.net5.cs index 46dba7941..09e91df18 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.net5.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.net5.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; @@ -35,7 +36,10 @@ private static DefaultComWrappers DefaultComWrappersInstance } internal static readonly ConditionalWeakTable InspectableInfoTable = new ConditionalWeakTable(); - [ThreadStatic] internal static Type CreateRCWType; + + [ThreadStatic] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] + internal static Type CreateRCWType; private static ComWrappers _comWrappers; private static object _comWrappersLock = new object(); @@ -82,12 +86,12 @@ internal static unsafe InspectableInfo GetInspectableInfo(IntPtr pThis) return InspectableInfoTable.GetValue(_this.GetType(), o => PregenerateNativeTypeInformation(o).inspectableInfo); } - public static T CreateRcwForComObject(IntPtr ptr) + public static T CreateRcwForComObject<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(IntPtr ptr) { return CreateRcwForComObject(ptr, true); } - private static T CreateRcwForComObject(IntPtr ptr, bool tryUseCache) + private static T CreateRcwForComObject<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(IntPtr ptr, bool tryUseCache) { if (ptr == IntPtr.Zero) { @@ -211,11 +215,30 @@ public static void InitializeComWrappers(ComWrappers wrappers = null) ComWrappers = wrappers; } - internal static Func GetTypedRcwFactory(Type implementationType) => TypedObjectFactoryCacheForType.GetOrAdd(implementationType, classType => CreateTypedRcwFactory(classType)); + internal static Func GetTypedRcwFactory([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type implementationType) => TypedObjectFactoryCacheForType.GetOrAdd(implementationType, classType => CreateTypedRcwFactory(classType)); - private static Func CreateFactoryForImplementationType(string runtimeClassName, Type implementationType) + private static Func CreateFactoryForImplementationType(string runtimeClassName, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type implementationType) { if (implementationType.IsGenericType) + { + Type genericImplType = GetGenericImplType(implementationType); + if (genericImplType != null) + { + var createRcw = genericImplType.GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IInspectable) }, null); + return (Func)createRcw.CreateDelegate(typeof(Func)); + } + } + + if (implementationType.IsInterface) + { + return obj => obj; + } + + var constructor = implementationType.GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null); + return (IInspectable obj) => constructor.Invoke(new[] { obj.ObjRef }); + + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] + static Type GetGenericImplType(Type implementationType) { var genericType = implementationType.GetGenericTypeDefinition(); @@ -240,21 +263,13 @@ private static Func CreateFactoryForImplementationType(str { genericImplType = typeof(IEnumerableImpl<>); } - - if (genericImplType != null) + else { - var createRcw = genericImplType.MakeGenericType(implementationType.GetGenericArguments()).GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IInspectable) }, null); - return (Func)createRcw.CreateDelegate(typeof(Func)); + return null; } - } - - if (implementationType.IsInterface) - { - return obj => obj; - } - var constructor = implementationType.GetConstructor(BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { typeof(IObjectReference) }, null); - return (IInspectable obj) => constructor.Invoke(new[] { obj.ObjRef }); + return genericImplType.MakeGenericType(implementationType.GetGenericArguments()); + } } } @@ -439,7 +454,13 @@ static unsafe DefaultComWrappers() protected override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) { - var vtableEntries = TypeVtableEntryTable.GetValue(obj.GetType(), (type) => + var vtableEntries = TypeVtableEntryTable.GetValue(obj.GetType(), ( +#if NET6_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#elif NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] +#endif + type) => { if (IsRuntimeImplementedRCW(type)) { diff --git a/src/WinRT.Runtime/GuidGenerator.cs b/src/WinRT.Runtime/GuidGenerator.cs index f87bd7f05..2028abe82 100644 --- a/src/WinRT.Runtime/GuidGenerator.cs +++ b/src/WinRT.Runtime/GuidGenerator.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Security.Cryptography; @@ -21,7 +22,11 @@ public static Guid GetGUID(Type type) return type.GetGuidType().GUID; } - public static Guid GetIID(Type type) + public static Guid GetIID( +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] +#endif + Type type) { type = type.GetGuidType(); if (!type.IsGenericType) @@ -31,7 +36,11 @@ public static Guid GetIID(Type type) return (Guid)type.GetField("PIID").GetValue(null); } - public static string GetSignature(Type type) + public static string GetSignature( +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] +#endif + Type type) { if (type == typeof(object)) { diff --git a/src/WinRT.Runtime/Interop/IActivationFactory.cs b/src/WinRT.Runtime/Interop/IActivationFactory.cs index 0acc53c69..1ba4f4614 100644 --- a/src/WinRT.Runtime/Interop/IActivationFactory.cs +++ b/src/WinRT.Runtime/Interop/IActivationFactory.cs @@ -9,7 +9,8 @@ namespace WinRT.Interop { [WindowsRuntimeType] - [Guid("00000035-0000-0000-C000-000000000046")] + [Guid("00000035-0000-0000-C000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IActivationFactory))] #if EMBED internal #else diff --git a/src/WinRT.Runtime/Interop/IAgileReference.net5.cs b/src/WinRT.Runtime/Interop/IAgileReference.net5.cs index b0bc9b85e..78ff5392b 100644 --- a/src/WinRT.Runtime/Interop/IAgileReference.net5.cs +++ b/src/WinRT.Runtime/Interop/IAgileReference.net5.cs @@ -7,14 +7,16 @@ namespace WinRT.Interop { [WindowsRuntimeType] - [Guid("C03F6A43-65A4-9818-987E-E0B810D2A6F2")] + [Guid("C03F6A43-65A4-9818-987E-E0B810D2A6F2")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IAgileReference))] internal interface IAgileReference { IObjectReference Resolve(Guid riid); } [WindowsRuntimeType] - [Guid("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90")] + [Guid("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IAgileObject))] #if EMBED internal #else @@ -26,7 +28,8 @@ interface IAgileObject } [WindowsRuntimeType] - [Guid("00000146-0000-0000-C000-000000000046")] + [Guid("00000146-0000-0000-C000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IGlobalInterfaceTable))] internal interface IGlobalInterfaceTable { IntPtr RegisterInterfaceInGlobal(IntPtr ptr, Guid riid); diff --git a/src/WinRT.Runtime/Interop/IAgileReference.netstandard2.0.cs b/src/WinRT.Runtime/Interop/IAgileReference.netstandard2.0.cs index 65f984eda..edbb4f13c 100644 --- a/src/WinRT.Runtime/Interop/IAgileReference.netstandard2.0.cs +++ b/src/WinRT.Runtime/Interop/IAgileReference.netstandard2.0.cs @@ -7,14 +7,16 @@ namespace WinRT.Interop { [WindowsRuntimeType] - [Guid("C03F6A43-65A4-9818-987E-E0B810D2A6F2")] + [Guid("C03F6A43-65A4-9818-987E-E0B810D2A6F2")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IAgileReference))] internal interface IAgileReference { IObjectReference Resolve(Guid riid); } [WindowsRuntimeType] - [Guid("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90")] + [Guid("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IAgileObject))] #if EMBED internal #else @@ -25,7 +27,8 @@ interface IAgileObject } [WindowsRuntimeType] - [Guid("00000146-0000-0000-C000-000000000046")] + [Guid("00000146-0000-0000-C000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IGlobalInterfaceTable))] internal interface IGlobalInterfaceTable { IntPtr RegisterInterfaceInGlobal(IntPtr ptr, Guid riid); diff --git a/src/WinRT.Runtime/Interop/IMarshal.cs b/src/WinRT.Runtime/Interop/IMarshal.cs index 32a519d15..dbd421014 100644 --- a/src/WinRT.Runtime/Interop/IMarshal.cs +++ b/src/WinRT.Runtime/Interop/IMarshal.cs @@ -13,7 +13,8 @@ internal enum MSHCTX : int { Local = 0, NoSharedMem = 1, DifferentMachine = 2, I internal enum MSHLFLAGS : int { Normal = 0, TableStrong = 1, TableWeak = 2, NoPing = 4 } [global::WinRT.WindowsRuntimeType("Windows.Foundation.UniversalApiContract")] - [Guid("00000003-0000-0000-c000-000000000046")] + [Guid("00000003-0000-0000-c000-000000000046")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IMarshal))] internal interface IMarshal { unsafe void GetUnmarshalClass(Guid* riid, IntPtr pv, MSHCTX dwDestContext, IntPtr pvDestContext, MSHLFLAGS mshlFlags, Guid* pCid); diff --git a/src/WinRT.Runtime/Interop/IWeakReferenceSource.net5.cs b/src/WinRT.Runtime/Interop/IWeakReferenceSource.net5.cs index d0597618c..1e09d0f78 100644 --- a/src/WinRT.Runtime/Interop/IWeakReferenceSource.net5.cs +++ b/src/WinRT.Runtime/Interop/IWeakReferenceSource.net5.cs @@ -10,6 +10,7 @@ namespace WinRT.Interop { [WindowsRuntimeType] [Guid("00000038-0000-0000-C000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IWeakReferenceSource))] #if EMBED internal #else @@ -22,6 +23,7 @@ interface IWeakReferenceSource [WindowsRuntimeType] [Guid("00000037-0000-0000-C000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IWeakReference))] #if EMBED internal #else diff --git a/src/WinRT.Runtime/Interop/IWeakReferenceSource.netstandard2.0.cs b/src/WinRT.Runtime/Interop/IWeakReferenceSource.netstandard2.0.cs index 24b447089..15cb04999 100644 --- a/src/WinRT.Runtime/Interop/IWeakReferenceSource.netstandard2.0.cs +++ b/src/WinRT.Runtime/Interop/IWeakReferenceSource.netstandard2.0.cs @@ -7,7 +7,8 @@ namespace WinRT.Interop { [WindowsRuntimeType] - [Guid("00000038-0000-0000-C000-000000000046")] + [Guid("00000038-0000-0000-C000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IWeakReferenceSource))] #if EMBED internal #else @@ -19,7 +20,8 @@ interface IWeakReferenceSource } [WindowsRuntimeType] - [Guid("00000037-0000-0000-C000-000000000046")] + [Guid("00000037-0000-0000-C000-000000000046")] + [WindowsRuntimeHelperType(typeof(global::ABI.WinRT.Interop.IWeakReference))] #if EMBED internal #else diff --git a/src/WinRT.Runtime/Marshalers.cs b/src/WinRT.Runtime/Marshalers.cs index dcb61f881..f03556e72 100644 --- a/src/WinRT.Runtime/Marshalers.cs +++ b/src/WinRT.Runtime/Marshalers.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; @@ -447,7 +448,11 @@ public static void DisposeAbiArray(object box) #endif class MarshalGeneric { +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] +#endif protected static readonly Type HelperType = typeof(T).GetHelperType(); + protected static readonly Type AbiType = typeof(T).GetAbiType(); protected static readonly Type MarshalerType = typeof(T).GetMarshalerType(); private static readonly bool MarshalByObjectReferenceValueSupported = typeof(T).GetMarshaler2Type() == typeof(ObjectReferenceValue); @@ -1038,6 +1043,14 @@ public static void DisposeAbi(IntPtr ptr) #endif struct MarshalInterface { +#if NET + [DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicFields | + DynamicallyAccessedMemberTypes.NonPublicFields | + DynamicallyAccessedMemberTypes.PublicNestedTypes | + DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods)] +#endif private static readonly Type HelperType = typeof(T).GetHelperType(); private static Func _ToAbi; private static Func _CreateMarshaler; @@ -1181,9 +1194,23 @@ private static Func BindCreateMarshaler() #else public #endif - static class MarshalInspectable + static class MarshalInspectable< +#if NET6_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#elif NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] +#endif + T> { - public static IObjectReference CreateMarshaler(T o, Guid iid, bool unwrapObject = true) + public static IObjectReference CreateMarshaler( +#if NET6_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#elif NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] +#endif + T o, + Guid iid, + bool unwrapObject = true) { if (o is null) { @@ -1205,12 +1232,27 @@ public static IObjectReference CreateMarshaler(T o, Guid iid, bool unwrapObje return ComWrappersSupport.CreateCCWForObject(o, iid); } - public static IObjectReference CreateMarshaler(T o, bool unwrapObject = true) + public static IObjectReference CreateMarshaler( +#if NET6_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#elif NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] +#endif + T o, + bool unwrapObject = true) { return CreateMarshaler(o, InterfaceIIDs.IInspectable_IID, unwrapObject); } - public static ObjectReferenceValue CreateMarshaler2(T o, Guid iid, bool unwrapObject = true) + public static ObjectReferenceValue CreateMarshaler2( +#if NET6_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#elif NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] +#endif + T o, + Guid iid, + bool unwrapObject = true) { if (o is null) { @@ -1232,8 +1274,13 @@ public static ObjectReferenceValue CreateMarshaler2(T o, Guid iid, bool unwrapOb return ComWrappersSupport.CreateCCWForObjectForMarshaling(o, iid); } - public static ObjectReferenceValue CreateMarshaler2(T o, bool unwrapObject = true) => - CreateMarshaler2(o, InterfaceIIDs.IInspectable_IID, unwrapObject); + public static ObjectReferenceValue CreateMarshaler2( +#if NET6_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#elif NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] +#endif + T o, bool unwrapObject = true) => CreateMarshaler2(o, InterfaceIIDs.IInspectable_IID, unwrapObject); public static IntPtr GetAbi(IObjectReference objRef) => objRef is null ? IntPtr.Zero : MarshalInterfaceHelper.GetAbi(objRef); @@ -1397,7 +1444,7 @@ internal static class Marshaler #if EMBED internal -#else +#else public #endif class Marshaler @@ -1599,6 +1646,9 @@ static Marshaler() RefAbiType = AbiType.MakeByRefType(); } +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] +#endif public static readonly Type AbiType; public static readonly Type RefAbiType; public static readonly Func CreateMarshaler; diff --git a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.net5.0.txt b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.net5.0.txt index 59248b033..b48d884cf 100644 --- a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.net5.0.txt +++ b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.net5.0.txt @@ -2,6 +2,7 @@ Compat issues with assembly WinRT.Runtime: MembersMustExist : Member 'public WinRT.ObjectReferenceValue ABI.System.EventHandler.CreateMarshaler2(System.EventHandler)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public System.EventHandler ABI.System.EventHandler.CreateRcw(System.IntPtr)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReferenceValue ABI.System.Nullable.CreateMarshaler2(System.Object)' does not exist in the reference but it does exist in the implementation. +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute' exists on 'ABI.System.Type.FromAbi(ABI.System.Type)' in the implementation but not the reference. MembersMustExist : Member 'public ABI.System.Type ABI.System.Type.GetAbi(ABI.System.Type.Pinnable)' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'ABI.System.Type.Pinnable' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReferenceValue ABI.System.Uri.CreateMarshaler2(System.Uri)' does not exist in the reference but it does exist in the implementation. @@ -21,10 +22,14 @@ MembersMustExist : Member 'public WinRT.ObjectReferenceValue ABI.System.Componen MembersMustExist : Member 'public System.ComponentModel.PropertyChangedEventHandler ABI.System.ComponentModel.PropertyChangedEventHandler.CreateRcw(System.IntPtr)' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'ABI.WinRT.Interop.IWeakReferenceSourceMethods' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Numerics.VectorExtensions' does not exist in the reference but it does exist in the implementation. +CannotRemoveAttribute : Attribute 'WinRT.WindowsRuntimeHelperTypeAttribute' exists on 'Windows.Foundation.Point' in the implementation but not the reference. +CannotRemoveAttribute : Attribute 'WinRT.WindowsRuntimeHelperTypeAttribute' exists on 'Windows.Foundation.Rect' in the implementation but not the reference. +CannotRemoveAttribute : Attribute 'WinRT.WindowsRuntimeHelperTypeAttribute' exists on 'Windows.Foundation.Size' in the implementation but not the reference. TypesMustExist : Type 'WinRT.ComWrappersHelper' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReference WinRT.ComWrappersSupport.GetObjectReferenceForInterface(System.IntPtr)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReference WinRT.ComWrappersSupport.GetObjectReferenceForInterface(System.IntPtr, System.Guid)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public void WinRT.ComWrappersSupport.RegisterObjectForInterface(System.Object, System.IntPtr, System.Runtime.InteropServices.CreateObjectFlags)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public void WinRT.ComWrappersSupport.RegisterProjectionTypeBaseTypeMapping(System.Collections.Generic.IDictionary)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'protected void WinRT.IObjectReference.AddRef(System.Boolean)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReference WinRT.IObjectReference.AsKnownPtr(System.IntPtr)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReferenceValue WinRT.IObjectReference.AsValue()' does not exist in the reference but it does exist in the implementation. @@ -32,6 +37,8 @@ MembersMustExist : Member 'public WinRT.ObjectReferenceValue WinRT.IObjectRefere MembersMustExist : Member 'public System.Int32 WinRT.IObjectReference.TryAs(System.Guid, System.IntPtr)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReferenceValue WinRT.MarshalDelegate.CreateMarshaler2(System.Object, System.Guid, System.Boolean)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public T WinRT.MarshalDelegate.FromAbi(System.IntPtr)' does not exist in the reference but it does exist in the implementation. +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on 'System.Type WinRT.Marshaler.AbiType' in the implementation but not the reference. +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on 'System.Type WinRT.MarshalGeneric.HelperType' in the implementation but not the reference. MembersMustExist : Member 'public WinRT.ObjectReferenceValue WinRT.MarshalInspectable.CreateMarshaler2(T, System.Boolean)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReferenceValue WinRT.MarshalInspectable.CreateMarshaler2(T, System.Guid, System.Boolean)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.IObjectReference WinRT.MarshalInspectable.CreateMarshaler(T, System.Guid, System.Boolean)' does not exist in the reference but it does exist in the implementation. @@ -49,6 +56,9 @@ MembersMustExist : Member 'public System.IntPtr WinRT.MarshalString.GetAbi()' do MembersMustExist : Member 'public System.IntPtr WinRT.MarshalString.GetAbi(WinRT.MarshalString.Pinnable)' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'WinRT.MarshalString.Pinnable' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'WinRT.ObjectReferenceValue' does not exist in the reference but it does exist in the implementation. +TypesMustExist : Type 'WinRT.WindowsRuntimeHelperTypeAttribute' does not exist in the reference but it does exist in the implementation. +CannotRemoveAttribute : Attribute 'WinRT.WindowsRuntimeHelperTypeAttribute' exists on 'WinRT.Interop.IActivationFactory' in the implementation but not the reference. +CannotRemoveAttribute : Attribute 'WinRT.WindowsRuntimeHelperTypeAttribute' exists on 'WinRT.Interop.IAgileObject' in the implementation but not the reference. TypesMustExist : Type 'WinRT.Interop.IWeakReference' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'WinRT.Interop.IWeakReferenceSource' does not exist in the reference but it does exist in the implementation. -Total Issues: 52 +Total Issues: 62 diff --git a/src/WinRT.Runtime/ObjectReference.cs b/src/WinRT.Runtime/ObjectReference.cs index 3fbd74c63..2ad8d65ce 100644 --- a/src/WinRT.Runtime/ObjectReference.cs +++ b/src/WinRT.Runtime/ObjectReference.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -122,8 +123,17 @@ protected IObjectReference(IntPtr thisPtr) Dispose(false); } - public ObjectReference As() => As(GuidGenerator.GetIID(typeof(T))); - public unsafe ObjectReference As(Guid iid) + public ObjectReference As< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + T>() => As(GuidGenerator.GetIID(typeof(T))); + + public unsafe ObjectReference As< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + T>(Guid iid) { Marshal.ThrowExceptionForHR(TryAs(iid, out var objRef)); return objRef; @@ -154,9 +164,17 @@ public unsafe TInterface AsInterface() #endif } - public int TryAs(out ObjectReference objRef) => TryAs(GuidGenerator.GetIID(typeof(T)), out objRef); + public int TryAs< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + T>(out ObjectReference objRef) => TryAs(GuidGenerator.GetIID(typeof(T)), out objRef); - public virtual unsafe int TryAs(Guid iid, out ObjectReference objRef) + public virtual unsafe int TryAs< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + T>(Guid iid, out ObjectReference objRef) { objRef = null; ThrowIfDisposed(); @@ -385,7 +403,11 @@ public unsafe ObjectReferenceValue AsValue(Guid iid) #else public #endif - class ObjectReference : IObjectReference + class ObjectReference< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif + T> : IObjectReference { private readonly T _vftbl; public T Vftbl @@ -472,7 +494,11 @@ private protected virtual T GetVftblForCurrentContext() } } - internal sealed class ObjectReferenceWithContext : ObjectReference + internal sealed class ObjectReferenceWithContext< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif + T> : ObjectReference { private readonly IntPtr _contextCallbackPtr; private readonly IntPtr _contextToken; @@ -607,7 +633,11 @@ public override ObjectReference AsKnownPtr(IntPtr ptr) return objRef; } - public override unsafe int TryAs(Guid iid, out ObjectReference objRef) + public override unsafe int TryAs< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif + U>(Guid iid, out ObjectReference objRef) { objRef = null; diff --git a/src/WinRT.Runtime/Projections.cs b/src/WinRT.Runtime/Projections.cs index 31eae71f3..82e2f7696 100644 --- a/src/WinRT.Runtime/Projections.cs +++ b/src/WinRT.Runtime/Projections.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; using System.Reflection; @@ -24,6 +25,7 @@ namespace WinRT static class Projections { private static readonly ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(); + private static readonly Dictionary CustomTypeToHelperTypeMappings = new Dictionary(); private static readonly Dictionary CustomAbiTypeToTypeMappings = new Dictionary(); private static readonly Dictionary CustomAbiTypeNameToTypeMappings = new Dictionary(StringComparer.Ordinal); @@ -97,12 +99,28 @@ static Projections() CustomTypeToHelperTypeMappings.Add(typeof(IVector<>), typeof(ABI.System.Collections.Generic.IList<>)); CustomTypeToHelperTypeMappings.Add(typeof(IMapView<,>), typeof(ABI.System.Collections.Generic.IReadOnlyDictionary<,>)); CustomTypeToHelperTypeMappings.Add(typeof(IVectorView<>), typeof(ABI.System.Collections.Generic.IReadOnlyList<>)); - CustomTypeToHelperTypeMappings.Add(typeof(global::Microsoft.UI.Xaml.Interop.IBindableVector), typeof(ABI.System.Collections.IList)); + CustomTypeToHelperTypeMappings.Add(typeof(Microsoft.UI.Xaml.Interop.IBindableVector), typeof(ABI.System.Collections.IList)); + +#if NET + CustomTypeToHelperTypeMappings.Add(typeof(ICollection<>), typeof(ABI.System.Collections.Generic.ICollection<>)); + CustomTypeToHelperTypeMappings.Add(typeof(IReadOnlyCollection<>), typeof(ABI.System.Collections.Generic.IReadOnlyCollection<>)); +#endif + RegisterCustomAbiTypeMappingNoLock(typeof(EventHandler), typeof(ABI.System.EventHandler)); CustomTypeToAbiTypeNameMappings.Add(typeof(System.Type), "Windows.UI.Xaml.Interop.TypeName"); } - public static void RegisterCustomAbiTypeMapping(Type publicType, Type abiType, string winrtTypeName, bool isRuntimeClass = false) + public static void RegisterCustomAbiTypeMapping( + Type publicType, +#if NET + [DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicNestedTypes)] +#endif + Type abiType, + string winrtTypeName, + bool isRuntimeClass = false) { rwlock.EnterWriteLock(); try @@ -115,7 +133,17 @@ public static void RegisterCustomAbiTypeMapping(Type publicType, Type abiType, s } } - private static void RegisterCustomAbiTypeMappingNoLock(Type publicType, Type abiType, string winrtTypeName, bool isRuntimeClass = false) + private static void RegisterCustomAbiTypeMappingNoLock( + Type publicType, +#if NET + [DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicNestedTypes)] +#endif + Type abiType, + string winrtTypeName, + bool isRuntimeClass = false) { CustomTypeToHelperTypeMappings.Add(publicType, abiType); CustomAbiTypeToTypeMappings.Add(abiType, publicType); @@ -128,6 +156,26 @@ private static void RegisterCustomAbiTypeMappingNoLock(Type publicType, Type abi } } + private static void RegisterCustomAbiTypeMappingNoLock( + Type publicType, +#if NET + [DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicNestedTypes)] +#endif + Type abiType) + { + CustomTypeToHelperTypeMappings.Add(publicType, abiType); + CustomAbiTypeToTypeMappings.Add(abiType, publicType); + } + +#if NET + [return: DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicNestedTypes)] +#endif public static Type FindCustomHelperTypeMapping(Type publicType, bool filterToRuntimeClass = false) { rwlock.EnterReadLock(); diff --git a/src/WinRT.Runtime/Projections/Bindable.net5.cs b/src/WinRT.Runtime/Projections/Bindable.net5.cs index 5b1a58d52..6f4d943ac 100644 --- a/src/WinRT.Runtime/Projections/Bindable.net5.cs +++ b/src/WinRT.Runtime/Projections/Bindable.net5.cs @@ -16,12 +16,14 @@ namespace Microsoft.UI.Xaml.Interop { [global::WinRT.WindowsRuntimeType] [Guid("036D2C08-DF29-41AF-8AA2-D774BE62BA6F")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Interop.IBindableIterable))] internal interface IBindableIterable { IBindableIterator First(); } [global::WinRT.WindowsRuntimeType] [Guid("6A1D6C07-076D-49F2-8314-F52C9C9A8331")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Interop.IBindableIterator))] internal interface IBindableIterator { bool MoveNext(); @@ -51,6 +53,7 @@ internal interface IBindableVector : IEnumerable } [global::WinRT.WindowsRuntimeType] [Guid("346DD6E7-976E-4BC3-815D-ECE243BC0F33")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Interop.IBindableVectorView))] internal interface IBindableVectorView : IEnumerable { object GetAt(uint index); diff --git a/src/WinRT.Runtime/Projections/Bindable.netstandard2.0.cs b/src/WinRT.Runtime/Projections/Bindable.netstandard2.0.cs index 66031b2c0..01b715ffb 100644 --- a/src/WinRT.Runtime/Projections/Bindable.netstandard2.0.cs +++ b/src/WinRT.Runtime/Projections/Bindable.netstandard2.0.cs @@ -15,12 +15,14 @@ namespace Microsoft.UI.Xaml.Interop { [global::WinRT.WindowsRuntimeType] [Guid("036D2C08-DF29-41AF-8AA2-D774BE62BA6F")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.System.Collections.IEnumerable))] internal interface IBindableIterable { IBindableIterator First(); } [global::WinRT.WindowsRuntimeType] [Guid("6A1D6C07-076D-49F2-8314-F52C9C9A8331")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Interop.IBindableIterator))] internal interface IBindableIterator { bool MoveNext(); @@ -50,6 +52,7 @@ internal interface IBindableVector : IEnumerable } [global::WinRT.WindowsRuntimeType] [Guid("346DD6E7-976E-4BC3-815D-ECE243BC0F33")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Interop.IBindableVectorView))] internal interface IBindableVectorView : IEnumerable { object GetAt(uint index); diff --git a/src/WinRT.Runtime/Projections/Geometry.cs b/src/WinRT.Runtime/Projections/Geometry.cs index e7ace5436..a7227556d 100644 --- a/src/WinRT.Runtime/Projections/Geometry.cs +++ b/src/WinRT.Runtime/Projections/Geometry.cs @@ -12,7 +12,8 @@ internal static class GSR public static string ArgumentOutOfRange_NeedNonNegNum = "Non-negative number required."; } - [global::WinRT.WindowsRuntimeType("Windows.Foundation.FoundationContract")] + [global::WinRT.WindowsRuntimeType("Windows.Foundation.FoundationContract")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Windows.Foundation.Point))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal @@ -104,7 +105,8 @@ public override int GetHashCode() } } - [global::WinRT.WindowsRuntimeType("Windows.Foundation.FoundationContract")] + [global::WinRT.WindowsRuntimeType("Windows.Foundation.FoundationContract")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Windows.Foundation.Rect))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal @@ -428,7 +430,8 @@ public override int GetHashCode() } } - [global::WinRT.WindowsRuntimeType("Windows.Foundation.FoundationContract")] + [global::WinRT.WindowsRuntimeType("Windows.Foundation.FoundationContract")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Windows.Foundation.Size))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal diff --git a/src/WinRT.Runtime/Projections/ICustomPropertyProvider.net5.cs b/src/WinRT.Runtime/Projections/ICustomPropertyProvider.net5.cs index 3a1d6e2d4..ca33a3457 100644 --- a/src/WinRT.Runtime/Projections/ICustomPropertyProvider.net5.cs +++ b/src/WinRT.Runtime/Projections/ICustomPropertyProvider.net5.cs @@ -8,7 +8,8 @@ namespace Microsoft.UI.Xaml.Data { - [global::WinRT.WindowsRuntimeType] + [global::WinRT.WindowsRuntimeType] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Data.ICustomProperty))] [Guid("30DA92C0-23E8-42A0-AE7C-734A0E5D2782")] interface ICustomProperty { diff --git a/src/WinRT.Runtime/Projections/ICustomPropertyProvider.netstandard2.0.cs b/src/WinRT.Runtime/Projections/ICustomPropertyProvider.netstandard2.0.cs index fcb55584a..889e1ab48 100644 --- a/src/WinRT.Runtime/Projections/ICustomPropertyProvider.netstandard2.0.cs +++ b/src/WinRT.Runtime/Projections/ICustomPropertyProvider.netstandard2.0.cs @@ -9,7 +9,8 @@ namespace Microsoft.UI.Xaml.Data { [global::WinRT.WindowsRuntimeType] - [Guid("30DA92C0-23E8-42A0-AE7C-734A0E5D2782")] + [Guid("30DA92C0-23E8-42A0-AE7C-734A0E5D2782")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Data.ICustomProperty))] interface ICustomProperty { object GetValue(object target); diff --git a/src/WinRT.Runtime/Projections/IReferenceArray.net5.cs b/src/WinRT.Runtime/Projections/IReferenceArray.net5.cs index a55a2cc08..08d3fd949 100644 --- a/src/WinRT.Runtime/Projections/IReferenceArray.net5.cs +++ b/src/WinRT.Runtime/Projections/IReferenceArray.net5.cs @@ -12,6 +12,7 @@ namespace Windows.Foundation // a "public" type for the type mapping definition. // IReferenceArray cannot appear in signatures, so it doesn't need to actually be public. [Guid("61C17707-2D65-11E0-9AE8-D48564015472")] + [WindowsRuntimeHelperType(typeof(global::ABI.Windows.Foundation.IReferenceArray<>))] internal interface IReferenceArray { T[] Value { get; } diff --git a/src/WinRT.Runtime/Projections/IReferenceArray.netstandard2.0.cs b/src/WinRT.Runtime/Projections/IReferenceArray.netstandard2.0.cs index 370881905..89047f7e6 100644 --- a/src/WinRT.Runtime/Projections/IReferenceArray.netstandard2.0.cs +++ b/src/WinRT.Runtime/Projections/IReferenceArray.netstandard2.0.cs @@ -11,7 +11,8 @@ namespace Windows.Foundation // Provide a stub definition of IReferenceArray so we have // a "public" type for the type mapping definition. // IReferenceArray cannot appear in signatures, so it doesn't need to actually be public. - [Guid("61C17707-2D65-11E0-9AE8-D48564015472")] + [Guid("61C17707-2D65-11E0-9AE8-D48564015472")] + [WindowsRuntimeHelperType(typeof(global::ABI.Windows.Foundation.IReferenceArray<>))] internal interface IReferenceArray { T[] Value { get; } diff --git a/src/WinRT.Runtime/Projections/Nullable.cs b/src/WinRT.Runtime/Projections/Nullable.cs index 4c44373d2..6bddb5b33 100644 --- a/src/WinRT.Runtime/Projections/Nullable.cs +++ b/src/WinRT.Runtime/Projections/Nullable.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; using System.Runtime.InteropServices; @@ -9,14 +10,17 @@ using WinRT.Interop; namespace ABI.Windows.Foundation -{ +{ using System; internal static class BoxedValueIReferenceImpl { private static global::ABI.System.Nullable.Vftbl AbiToProjectionVftable; - public static IntPtr AbiToProjectionVftablePtr; - + public static IntPtr AbiToProjectionVftablePtr; + +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "ABI types used with MakeGenericType are not reflected on.")] +#endif static unsafe BoxedValueIReferenceImpl() { AbiToProjectionVftable = new global::ABI.System.Nullable.Vftbl diff --git a/src/WinRT.Runtime/Projections/Type.cs b/src/WinRT.Runtime/Projections/Type.cs index a5b2281b0..80bcd751d 100644 --- a/src/WinRT.Runtime/Projections/Type.cs +++ b/src/WinRT.Runtime/Projections/Type.cs @@ -3,6 +3,9 @@ using System; using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Reflection; using WinRT; namespace ABI.System @@ -56,9 +59,15 @@ public ref readonly char GetPinnableReference() private static (String Name, TypeKind Kind) ToAbi(global::System.Type value) { - TypeKind kind = TypeKind.Custom; - - if (value is object) +#if NET + if (value is FakeMetadataType fakeMetadataType) + { + return (fakeMetadataType.FullName, TypeKind.Metadata); + } +#endif + + TypeKind kind = TypeKind.Custom; + if (value is not null) { if (value.IsPrimitive) { @@ -116,8 +125,12 @@ public static Type GetAbi(Marshaler m) Name = MarshalString.GetAbi(m.Name), Kind = m.Kind }; - } - + } + +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Any types which are trimmed are not used by managed user code and there is fallback logic to handle that.")] +#endif public static global::System.Type FromAbi(Type value) { string name = MarshalString.FromAbi(value.Name); @@ -126,12 +139,24 @@ public static Type GetAbi(Marshaler m) return null; } - if(value.Kind == TypeKind.Custom) + if (value.Kind == TypeKind.Custom) { return global::System.Type.GetType(name); } - return TypeNameSupport.FindTypeByNameCached(name); + var type = TypeNameSupport.FindTypeByNameCached(name); + +#if NET + // The type might have been trimmed, represent it with a fake type if requested + // by the the Xaml metadata provider. Given there are no C# references to it, it shouldn't + // be used, but if it is, an exception will be thrown. + if (type == null && value.Kind == TypeKind.Metadata) + { + type = FakeMetadataType.GetFakeMetadataType(name); + } +#endif + + return type; } public static unsafe void CopyAbi(Marshaler arg, IntPtr dest) => @@ -157,5 +182,202 @@ public static string GetGuidSignature() { return "struct(Windows.UI.Xaml.Interop.TypeName;string;enum(Windows.UI.Xaml.Interop.TypeKind;i4))"; } + } + + // Restricting to NET5 or greater as TypeInfo doesn't expose a constructor on .NET Standard 2.0 and we only need this + // for WinUI scenarios. +#if NET + internal sealed class FakeMetadataType : global::System.Reflection.TypeInfo + { + private static readonly ConcurrentDictionary fakeMetadataTypeCache = new(StringComparer.Ordinal); + + private readonly string fullName; + + private FakeMetadataType(string fullName) + { + this.fullName = fullName; + } + + internal static FakeMetadataType GetFakeMetadataType(string name) + { + return fakeMetadataTypeCache.GetOrAdd(name, (name) => new FakeMetadataType(name)); + } + + public override Assembly Assembly => throw new InvalidOperationException(); + + public override string AssemblyQualifiedName => throw new InvalidOperationException(); + + public override global::System.Type BaseType => throw new InvalidOperationException(); + + public override string FullName => fullName; + + public override Guid GUID => throw new InvalidOperationException(); + + public override Module Module => throw new InvalidOperationException(); + + public override string Namespace => throw new InvalidOperationException(); + + public override global::System.Type UnderlyingSystemType => throw new InvalidOperationException(); + + public override string Name => throw new InvalidOperationException(); + + public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override object[] GetCustomAttributes(bool inherit) + { + throw new InvalidOperationException(); + } + + public override object[] GetCustomAttributes(global::System.Type attributeType, bool inherit) + { + throw new InvalidOperationException(); + } + + public override global::System.Type GetElementType() + { + throw new InvalidOperationException(); + } + + public override EventInfo GetEvent(string name, BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override EventInfo[] GetEvents(BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override FieldInfo GetField(string name, BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override FieldInfo[] GetFields(BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + +#if NET6_0_OR_GREATER + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + public override global::System.Type GetInterface(string name, bool ignoreCase) + { + throw new InvalidOperationException(); + } + + public override global::System.Type[] GetInterfaces() + { + throw new InvalidOperationException(); + } + + public override MemberInfo[] GetMembers(BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override MethodInfo[] GetMethods(BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override global::System.Type GetNestedType(string name, BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override global::System.Type[] GetNestedTypes(BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) + { + throw new InvalidOperationException(); + } + + public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) + { + throw new InvalidOperationException(); + } + + public override bool IsDefined(global::System.Type attributeType, bool inherit) + { + throw new InvalidOperationException(); + } + + protected override TypeAttributes GetAttributeFlagsImpl() + { + throw new InvalidOperationException(); + } + + protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, global::System.Type[] types, ParameterModifier[] modifiers) + { + throw new InvalidOperationException(); + } + + protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, global::System.Type[] types, ParameterModifier[] modifiers) + { + throw new InvalidOperationException(); + } + + protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, global::System.Type returnType, global::System.Type[] types, ParameterModifier[] modifiers) + { + throw new InvalidOperationException(); + } + + protected override bool HasElementTypeImpl() + { + throw new InvalidOperationException(); + } + + protected override bool IsArrayImpl() + { + throw new InvalidOperationException(); + } + + protected override bool IsByRefImpl() + { + throw new InvalidOperationException(); + } + + protected override bool IsCOMObjectImpl() + { + throw new InvalidOperationException(); + } + + protected override bool IsPointerImpl() + { + throw new InvalidOperationException(); + } + + protected override bool IsPrimitiveImpl() + { + throw new InvalidOperationException(); + } + + public override string ToString() + { + return fullName; + } + + public override bool Equals(object o) + { + return ReferenceEquals(this, o); + } + + public override bool Equals(global::System.Type o) + { + return ReferenceEquals(this, o); + } + + public override int GetHashCode() + { + return fullName.GetHashCode(); + } } +#endif } diff --git a/src/WinRT.Runtime/TypeExtensions.cs b/src/WinRT.Runtime/TypeExtensions.cs index 14a25154e..02683ad55 100644 --- a/src/WinRT.Runtime/TypeExtensions.cs +++ b/src/WinRT.Runtime/TypeExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace WinRT @@ -14,48 +15,109 @@ namespace WinRT #endif static class TypeExtensions { - private readonly static ConcurrentDictionary HelperTypeCache = new ConcurrentDictionary(); - + private readonly static ConcurrentDictionary HelperTypeCache = new ConcurrentDictionary(); + +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicNestedTypes | + DynamicallyAccessedMemberTypes.PublicFields)] +#endif public static Type FindHelperType(this Type type) { - return HelperTypeCache.GetOrAdd(type, (type) => + return HelperTypeCache.GetOrAdd(type, +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicNestedTypes | + DynamicallyAccessedMemberTypes.PublicFields)] +#endif + (type) => { if (typeof(Exception).IsAssignableFrom(type)) { type = typeof(Exception); } Type customMapping = Projections.FindCustomHelperTypeMapping(type); - if (customMapping is object) + if (customMapping is not null) { return customMapping; } - string fullTypeName = type.FullName; - string ccwTypePrefix = "ABI.Impl."; - if (fullTypeName.StartsWith(ccwTypePrefix, StringComparison.Ordinal)) - { - fullTypeName = fullTypeName.Substring(ccwTypePrefix.Length); + var helperTypeAtribute = type.GetCustomAttribute(); + if (helperTypeAtribute is not null) + { + return GetHelperTypeFromAttribute(helperTypeAtribute, type); } - var helper = $"ABI.{fullTypeName}"; - return type.Assembly.GetType(helper) ?? Type.GetType(helper); - }); - } - + return FindHelperTypeFallback(type); + }); + +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "No members of the generic type are dynamically accessed other than for the attributes on it.")] + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + static Type GetHelperTypeFromAttribute(WindowsRuntimeHelperTypeAttribute helperTypeAtribute, Type type) + { + if (type.IsGenericType) + { + return helperTypeAtribute.HelperType.MakeGenericType(type.GetGenericArguments()); + } + else + { + return helperTypeAtribute.HelperType; + } + } + +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "This is a fallback for compat purposes with existing projections. " + + "Applications which make use of trimming will make use of updated projections that won't hit this code path.")] +#endif + static Type FindHelperTypeFallback(Type type) + { + string fullTypeName = type.FullName; + string ccwTypePrefix = "ABI.Impl."; + if (fullTypeName.StartsWith(ccwTypePrefix, StringComparison.Ordinal)) + { + fullTypeName = fullTypeName.Substring(ccwTypePrefix.Length); + } + + var helper = $"ABI.{fullTypeName}"; + return type.Assembly.GetType(helper) ?? Type.GetType(helper); + } + } + +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicNestedTypes)] +#endif public static Type GetHelperType(this Type type) { var helperType = type.FindHelperType(); if (helperType is object) return helperType; throw new InvalidOperationException($"Target type is not a projected type: {type.FullName}."); - } - + } + +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] +#endif public static Type GetGuidType(this Type type) { return type.IsDelegate() ? type.GetHelperType() : type; - } - - public static Type FindVftblType(this Type helperType) + } + +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)] +#endif + public static Type FindVftblType( +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes)] +#endif + this Type helperType) { Type vftblType = helperType.GetNestedType("Vftbl"); if (vftblType is null) @@ -69,7 +131,11 @@ public static Type FindVftblType(this Type helperType) return vftblType; } - internal static IntPtr GetAbiToProjectionVftblPtr(this Type helperType) + internal static IntPtr GetAbiToProjectionVftblPtr( +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] +#endif + this Type helperType) { return (IntPtr)(helperType.FindVftblType() ?? helperType).GetField("AbiToProjectionVftablePtr", BindingFlags.Public | BindingFlags.Static).GetValue(null); } @@ -118,7 +184,7 @@ internal static Type GetAuthoringMetadataType(this Type type) return AuthoringMetadataTypeCache.GetOrAdd(type, (type) => { var ccwTypeName = $"ABI.Impl.{type.FullName}"; - return type.Assembly.GetType(ccwTypeName, false) ?? Type.GetType(ccwTypeName, false); + return type.Assembly.GetType(ccwTypeName, false); }); } } diff --git a/src/WinRT.Runtime/TypeNameSupport.cs b/src/WinRT.Runtime/TypeNameSupport.cs index 889d7009a..7814f85bd 100644 --- a/src/WinRT.Runtime/TypeNameSupport.cs +++ b/src/WinRT.Runtime/TypeNameSupport.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Text; @@ -34,33 +35,71 @@ enum TypeNameGenerationFlags #endif static class TypeNameSupport { - private static readonly List projectionAssemblies = new List(); + private static readonly List projectionAssemblies = new List(); + private static readonly List> projectionTypeNameToBaseTypeNameMappings = new List>(); private static readonly ConcurrentDictionary typeNameCache = new ConcurrentDictionary(StringComparer.Ordinal) { ["TrackerCollection"] = null }; + private static readonly ConcurrentDictionary baseRcwTypeCache = new ConcurrentDictionary(StringComparer.Ordinal) { ["TrackerCollection"] = null }; public static void RegisterProjectionAssembly(Assembly assembly) { projectionAssemblies.Add(assembly); - } - + } + + internal static void RegisterProjectionTypeBaseTypeMapping(IDictionary typeNameToBaseTypeNameMapping) + { + projectionTypeNameToBaseTypeNameMappings.Add(typeNameToBaseTypeNameMapping); + } + +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif + public static Type FindRcwTypeByNameCached(string runtimeClassName) + { + // Try to get the given type name. If it is not found, the type might have been trimmed. + // Due to that, check if one of the base types exists and if so use that instead for the RCW type. + var rcwType = FindTypeByNameCached(runtimeClassName); + if (rcwType is null) + { + rcwType = baseRcwTypeCache.GetOrAdd(runtimeClassName, +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif + (runtimeClassName) => + { + var resolvedBaseType = projectionTypeNameToBaseTypeNameMappings.Find((dict) => dict.ContainsKey(runtimeClassName))?[runtimeClassName]; + return resolvedBaseType is not null ? FindRcwTypeByNameCached(resolvedBaseType) : null; + }); + } + + return rcwType; + } + /// /// Parses and loads the given type name, if not found in the cache. /// /// The runtime class name to attempt to parse. /// The type, if found. Null otherwise +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif public static Type FindTypeByNameCached(string runtimeClassName) { - return typeNameCache.GetOrAdd(runtimeClassName, (runtimeClassName) => - { - Type implementationType = null; - try - { - implementationType = FindTypeByName(runtimeClassName.AsSpan()).type; - } - catch (Exception) + return typeNameCache.GetOrAdd(runtimeClassName, +#if NET + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif + (runtimeClassName) => { - } - return implementationType; - }); + Type implementationType = null; + try + { + implementationType = FindTypeByName(runtimeClassName.AsSpan()).type; + } + catch (Exception) + { + } + return implementationType; + }); } /// @@ -90,8 +129,8 @@ public static (Type type, int remaining) FindTypeByName(ReadOnlySpan runti var (genericTypeName, genericTypes, remaining) = ParseGenericTypeName(runtimeClassName); return (FindTypeByNameCore(genericTypeName, genericTypes), remaining); } - } - + } + /// /// Resolve a type from the given simple type name and the provided generic parameters. /// @@ -102,6 +141,11 @@ public static (Type type, int remaining) FindTypeByName(ReadOnlySpan runti /// We look up the type dynamically because at this point in the stack we can't know /// the full type closure of the application. /// +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Any types which are trimmed are not used by user code and there is fallback logic to handle that.")] + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif private static Type FindTypeByNameCore(string runtimeClassName, Type[] genericTypes) { Type resolvedType = Projections.FindCustomTypeForAbiTypeName(runtimeClassName); @@ -111,7 +155,7 @@ private static Type FindTypeByNameCore(string runtimeClassName, Type[] genericTy if (genericTypes is null) { Type primitiveType = ResolvePrimitiveType(runtimeClassName); - if (primitiveType is object) + if (primitiveType is not null) { return primitiveType; } @@ -120,7 +164,7 @@ private static Type FindTypeByNameCore(string runtimeClassName, Type[] genericTy foreach (var assembly in projectionAssemblies) { Type type = assembly.GetType(runtimeClassName); - if (type is object) + if (type is not null) { resolvedType = type; break; @@ -133,15 +177,15 @@ private static Type FindTypeByNameCore(string runtimeClassName, Type[] genericTy foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { Type type = assembly.GetType(runtimeClassName); - if (type is object) + if (type is not null) { resolvedType = type; break; } } - } + } - if (resolvedType is object) + if (resolvedType is not null) { if (genericTypes != null) { diff --git a/src/WinRT.Runtime/WinRT.Runtime.csproj b/src/WinRT.Runtime/WinRT.Runtime.csproj index a473b85dd..317f18f1b 100644 --- a/src/WinRT.Runtime/WinRT.Runtime.csproj +++ b/src/WinRT.Runtime/WinRT.Runtime.csproj @@ -21,6 +21,8 @@ Copyright (c) Microsoft Corporation. All rights reserved. true key.snk + true + true diff --git a/src/build.cmd b/src/build.cmd index 9c55ec243..90dcea672 100644 --- a/src/build.cmd +++ b/src/build.cmd @@ -75,6 +75,8 @@ if "%cswinrt_assembly_version%"=="" set cswinrt_assembly_version=0.0.0.0 if "%cswinrt_baseline_breaking_compat_errors%"=="" set cswinrt_baseline_breaking_compat_errors=false if "%cswinrt_baseline_assembly_version_compat_errors%"=="" set cswinrt_baseline_assembly_version_compat_errors=false +set cswinrt_functional_tests=JsonValueFunctionCalls, ClassActivation, Structs, Events, DynamicInterfaceCasting, Collections, Async, DerivedClassActivation, DerivedClassAsBaseClass, CCW + rem Generate prerelease targets file to exercise build warnings set prerelease_targets=%this_dir%..\nuget\Microsoft.Windows.CsWinRT.Prerelease.targets rem Create default %prerelease_targets% @@ -137,6 +139,17 @@ if ErrorLevel 1 ( echo ERROR: Build failed exit /b !ErrorLevel! ) + +if "%cswinrt_platform%" NEQ "arm" ( + if "%cswinrt_platform%" NEQ "arm64" ( + echo Publishing functional tests for %cswinrt_platform% %cswinrt_configuration% + for %%a in (%cswinrt_functional_tests%) do ( + echo Publishing %%a + call :exec %msbuild_path%msbuild.exe /t:restore /t:publish %cswinrt_build_params% /p:platform=%cswinrt_platform%;configuration=%cswinrt_configuration%;VersionNumber=%cswinrt_version_number%;VersionString=%cswinrt_version_string%;AssemblyVersionNumber=%cswinrt_assembly_version%;GenerateTestProjection=true;BaselineAllAPICompatError=%cswinrt_baseline_breaking_compat_errors%;BaselineAllMatchingRefApiCompatError=%cswinrt_baseline_assembly_version_compat_errors% /p:solutiondir=%this_dir% %this_dir%Tests\FunctionalTests\%%a\%%a.csproj + ) + ) +) + if "%cswinrt_build_only%"=="true" goto :eof :buildembedded @@ -222,6 +235,23 @@ if ErrorLevel 1 ( exit /b !ErrorLevel! ) +:functionaltest +rem Run functional tests +echo Running cswinrt functional tests for %cswinrt_platform% %cswinrt_configuration% + +for %%a in (%cswinrt_functional_tests%) do ( + echo Running %%a + + call :exec %this_dir%Tests\FunctionalTests\%%a\bin\%cswinrt_configuration%\net6.0\win10-%cswinrt_platform%\publish\%%a.exe + if !errorlevel! NEQ 100 ( + echo. + echo ERROR: Functional test '%%a' failed with !errorlevel!, skipping NuGet pack + exit /b !ErrorLevel! + ) +) + +if "%cswinrt_label%"=="functionaltest" exit /b 0 + :package rem We set the properties of the CsWinRT.nuspec here, and pass them as the -Properties option when we call `nuget pack` set cswinrt_bin_dir=%this_dir%_build\%cswinrt_platform%\%cswinrt_configuration%\cswinrt\bin\ @@ -247,5 +277,4 @@ echo. ) else ( %* ) -goto :eof - +goto :eof \ No newline at end of file diff --git a/src/cswinrt.sln b/src/cswinrt.sln index cb5140050..4786d8219 100644 --- a/src/cswinrt.sln +++ b/src/cswinrt.sln @@ -125,6 +125,35 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_component_fast", "Test EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OOPExe", "Tests\OOPExe\OOPExe.csproj", "{8DB50E24-9599-4890-939D-C87C1EC5DDAD}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonValueFunctionCalls", "Tests\FunctionalTests\JsonValueFunctionCalls\JsonValueFunctionCalls.csproj", "{EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FunctionalTests", "FunctionalTests", "{5ECC38F0-16FD-47E1-B8DC-8C474008AD55}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PublishProfiles", "PublishProfiles", "{6FBE79A9-9D6D-4436-9F84-797ED1C9F676}" + ProjectSection(SolutionItems) = preProject + Tests\FunctionalTests\PublishProfiles\win10-arm64.pubxml = Tests\FunctionalTests\PublishProfiles\win10-arm64.pubxml + Tests\FunctionalTests\PublishProfiles\win10-x64.pubxml = Tests\FunctionalTests\PublishProfiles\win10-x64.pubxml + Tests\FunctionalTests\PublishProfiles\win10-x86.pubxml = Tests\FunctionalTests\PublishProfiles\win10-x86.pubxml + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClassActivation", "Tests\FunctionalTests\ClassActivation\ClassActivation.csproj", "{F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DerivedClassActivation", "Tests\FunctionalTests\DerivedClassActivation\DerivedClassActivation.csproj", "{1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Events", "Tests\FunctionalTests\Events\Events.csproj", "{2059A2D5-6E35-4CCF-A385-8A442FC6AD95}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Structs", "Tests\FunctionalTests\Structs\Structs.csproj", "{5EC7393C-CEBA-42F2-9105-D39315C602EC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Collections", "Tests\FunctionalTests\Collections\Collections.csproj", "{EA892842-E3C6-45B3-9D3F-3C1FE41D5239}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Async", "Tests\FunctionalTests\Async\Async.csproj", "{94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynamicInterfaceCasting", "Tests\FunctionalTests\DynamicInterfaceCasting\DynamicInterfaceCasting.csproj", "{756947F1-26D7-49ED-A4E8-8C4F126182C8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DerivedClassAsBaseClass", "Tests\FunctionalTests\DerivedClassAsBaseClass\DerivedClassAsBaseClass.csproj", "{E3AEC9A4-D1A3-448D-B980-F82894792AF1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CCW", "Tests\FunctionalTests\CCW\CCW.csproj", "{C44DB047-5DF0-4732-98F4-A181D3AD8A7F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -516,18 +545,138 @@ Global {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x64.Build.0 = Release|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x86.ActiveCfg = Release|Win32 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x86.Build.0 = Release|Win32 - {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Debug|ARM.ActiveCfg = Debug|x86 - {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Debug|ARM64.ActiveCfg = Debug|x86 + {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Debug|ARM.ActiveCfg = Debug|ARM + {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Debug|ARM64.ActiveCfg = Debug|ARM64 {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Debug|x64.ActiveCfg = Debug|x64 {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Debug|x64.Build.0 = Debug|x64 {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Debug|x86.ActiveCfg = Debug|x86 {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Debug|x86.Build.0 = Debug|x86 - {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Release|ARM.ActiveCfg = Release|x86 - {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Release|ARM64.ActiveCfg = Release|x86 + {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Release|ARM.ActiveCfg = Release|ARM + {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Release|ARM64.ActiveCfg = Release|ARM64 {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Release|x64.ActiveCfg = Release|x64 {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Release|x64.Build.0 = Release|x64 {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Release|x86.ActiveCfg = Release|x86 {8DB50E24-9599-4890-939D-C87C1EC5DDAD}.Release|x86.Build.0 = Release|x86 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Debug|ARM.ActiveCfg = Debug|ARM + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Debug|x64.ActiveCfg = Debug|x64 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Debug|x64.Build.0 = Debug|x64 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Debug|x86.ActiveCfg = Debug|x86 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Debug|x86.Build.0 = Debug|x86 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Release|ARM.ActiveCfg = Release|ARM + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Release|ARM64.ActiveCfg = Release|ARM64 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Release|x64.ActiveCfg = Release|x64 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Release|x64.Build.0 = Release|x64 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Release|x86.ActiveCfg = Release|x86 + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8}.Release|x86.Build.0 = Release|x86 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Debug|ARM.ActiveCfg = Debug|ARM + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Debug|x64.ActiveCfg = Debug|x64 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Debug|x64.Build.0 = Debug|x64 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Debug|x86.ActiveCfg = Debug|x86 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Debug|x86.Build.0 = Debug|x86 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Release|ARM.ActiveCfg = Release|ARM + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Release|ARM64.ActiveCfg = Release|ARM64 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Release|x64.ActiveCfg = Release|x64 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Release|x64.Build.0 = Release|x64 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Release|x86.ActiveCfg = Release|x86 + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E}.Release|x86.Build.0 = Release|x86 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Debug|ARM.ActiveCfg = Debug|ARM + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Debug|x64.ActiveCfg = Debug|x64 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Debug|x64.Build.0 = Debug|x64 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Debug|x86.ActiveCfg = Debug|x86 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Debug|x86.Build.0 = Debug|x86 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Release|ARM.ActiveCfg = Release|ARM + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Release|ARM64.ActiveCfg = Release|ARM64 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Release|x64.ActiveCfg = Release|x64 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Release|x64.Build.0 = Release|x64 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Release|x86.ActiveCfg = Release|x86 + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D}.Release|x86.Build.0 = Release|x86 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Debug|ARM.ActiveCfg = Debug|ARM + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Debug|x64.ActiveCfg = Debug|x64 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Debug|x64.Build.0 = Debug|x64 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Debug|x86.ActiveCfg = Debug|x86 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Debug|x86.Build.0 = Debug|x86 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Release|ARM.ActiveCfg = Release|ARM + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Release|ARM64.ActiveCfg = Release|ARM64 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Release|x64.ActiveCfg = Release|x64 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Release|x64.Build.0 = Release|x64 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Release|x86.ActiveCfg = Release|x86 + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95}.Release|x86.Build.0 = Release|x86 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Debug|ARM.ActiveCfg = Debug|ARM + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Debug|x64.ActiveCfg = Debug|x64 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Debug|x64.Build.0 = Debug|x64 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Debug|x86.ActiveCfg = Debug|x86 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Debug|x86.Build.0 = Debug|x86 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Release|ARM.ActiveCfg = Release|ARM + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Release|ARM64.ActiveCfg = Release|ARM64 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Release|x64.ActiveCfg = Release|x64 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Release|x64.Build.0 = Release|x64 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Release|x86.ActiveCfg = Release|x86 + {5EC7393C-CEBA-42F2-9105-D39315C602EC}.Release|x86.Build.0 = Release|x86 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Debug|ARM.ActiveCfg = Debug|ARM + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Debug|x64.ActiveCfg = Debug|x64 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Debug|x64.Build.0 = Debug|x64 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Debug|x86.ActiveCfg = Debug|x86 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Debug|x86.Build.0 = Debug|x86 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Release|ARM.ActiveCfg = Release|ARM + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Release|ARM64.ActiveCfg = Release|ARM64 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Release|x64.ActiveCfg = Release|x64 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Release|x64.Build.0 = Release|x64 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Release|x86.ActiveCfg = Release|x86 + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239}.Release|x86.Build.0 = Release|x86 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Debug|ARM.ActiveCfg = Debug|ARM + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Debug|x64.ActiveCfg = Debug|x64 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Debug|x64.Build.0 = Debug|x64 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Debug|x86.ActiveCfg = Debug|x86 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Debug|x86.Build.0 = Debug|x86 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Release|ARM.ActiveCfg = Release|ARM + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Release|ARM64.ActiveCfg = Release|ARM64 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Release|x64.ActiveCfg = Release|x64 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Release|x64.Build.0 = Release|x64 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Release|x86.ActiveCfg = Release|x86 + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05}.Release|x86.Build.0 = Release|x86 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Debug|ARM.ActiveCfg = Debug|ARM + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Debug|x64.ActiveCfg = Debug|x64 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Debug|x64.Build.0 = Debug|x64 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Debug|x86.ActiveCfg = Debug|x86 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Debug|x86.Build.0 = Debug|x86 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Release|ARM.ActiveCfg = Release|ARM + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Release|ARM64.ActiveCfg = Release|ARM64 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Release|x64.ActiveCfg = Release|x64 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Release|x64.Build.0 = Release|x64 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Release|x86.ActiveCfg = Release|x86 + {756947F1-26D7-49ED-A4E8-8C4F126182C8}.Release|x86.Build.0 = Release|x86 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Debug|ARM.ActiveCfg = Debug|ARM + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Debug|x64.ActiveCfg = Debug|x64 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Debug|x64.Build.0 = Debug|x64 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Debug|x86.ActiveCfg = Debug|x86 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Debug|x86.Build.0 = Debug|x86 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Release|ARM.ActiveCfg = Release|ARM + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Release|ARM64.ActiveCfg = Release|ARM64 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Release|x64.ActiveCfg = Release|x64 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Release|x64.Build.0 = Release|x64 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Release|x86.ActiveCfg = Release|x86 + {E3AEC9A4-D1A3-448D-B980-F82894792AF1}.Release|x86.Build.0 = Release|x86 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Debug|ARM.ActiveCfg = Debug|ARM + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Debug|x64.ActiveCfg = Debug|x64 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Debug|x64.Build.0 = Debug|x64 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Debug|x86.ActiveCfg = Debug|x86 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Debug|x86.Build.0 = Debug|x86 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Release|ARM.ActiveCfg = Release|ARM + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Release|ARM64.ActiveCfg = Release|ARM64 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Release|x64.ActiveCfg = Release|x64 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Release|x64.Build.0 = Release|x64 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Release|x86.ActiveCfg = Release|x86 + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -558,6 +707,18 @@ Global {80F0EC48-5536-49D6-8ED1-B1F4CED88073} = {6D41796B-9904-40B8-BBCB-40B2D1BAE44B} {0E0ACA62-A92F-44CF-BD41-AEB541946DF8} = {CFB651EC-DAA4-4A11-ABCD-C77F90602EB5} {8DB50E24-9599-4890-939D-C87C1EC5DDAD} = {CFB651EC-DAA4-4A11-ABCD-C77F90602EB5} + {EE5B4B23-5D4B-4DFB-8DC9-4DBB1B735CC8} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} = {CFB651EC-DAA4-4A11-ABCD-C77F90602EB5} + {6FBE79A9-9D6D-4436-9F84-797ED1C9F676} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {F0D6034B-5368-4B13-BBB9-4ABBC535AA0E} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {1AB3E799-A573-4704-9AC3-FF7D6BBA8D6D} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {2059A2D5-6E35-4CCF-A385-8A442FC6AD95} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {5EC7393C-CEBA-42F2-9105-D39315C602EC} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {EA892842-E3C6-45B3-9D3F-3C1FE41D5239} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {94E1D7EA-F932-4C7F-8EE8-5DEFD8474D05} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {756947F1-26D7-49ED-A4E8-8C4F126182C8} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {E3AEC9A4-D1A3-448D-B980-F82894792AF1} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} + {C44DB047-5DF0-4732-98F4-A181D3AD8A7F} = {5ECC38F0-16FD-47E1-B8DC-8C474008AD55} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5AE8C9D7-2613-4E1A-A4F2-579BAC28D0A2} diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index d7281bf9e..5d8b5b025 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -3110,6 +3110,29 @@ private % AsInternal(InterfaceTag<%> _) => % ?? Make_%(); db_path.stem().string()); } + void write_winrt_helper_type_attribute(writer& w, TypeDef const& type) + { + if (get_category(type) == category::struct_type && is_type_blittable(type)) + { + w.write(R"([global::WinRT.WindowsRuntimeHelperType])"); + return; + } + + w.write(R"([global::WinRT.WindowsRuntimeHelperType(typeof(%%))])", + bind(type, typedef_name_type::ABI, false), + bind([&](writer& w) + { + if (distance(type.GenericParam()) == 0) + { + return; + } + + // Writes out the generic definition without the types. + separator s{ w }; + w.write("<%>", bind_each([&](writer& /*w*/, GenericParam const& /*gp*/){ s(); }, type.GenericParam())); + })); + } + auto get_invoke_info(writer& w, MethodDef const& method, uint32_t const& abi_methods_start_index = INSPECTABLE_METHOD_COUNT) { TypeDef const& type = method.Parent(); @@ -5773,8 +5796,16 @@ IInspectableVftbl = global::WinRT.IInspectable.Vftbl.AbiToProjectionVftable, void write_authoring_metadata_type(writer& w, TypeDef const& type) { - w.write("%%internal class % {}\n", + w.write("%%%internal class % {}\n", bind(type), + [&](writer& w) + { + auto category = get_category(type); + if (category == category::delegate_type || category == category::struct_type) + { + write_winrt_helper_type_attribute(w, type); + } + }, bind(type, false), bind(type, typedef_name_type::CCW, false)); } @@ -5827,7 +5858,7 @@ IInspectableVftbl = global::WinRT.IInspectable.Vftbl.AbiToProjectionVftable, XLANG_ASSERT(get_category(type) == category::interface_type); auto type_name = write_type_name_temp(w, type, "%", typedef_name_type::CCW); - w.write(R"(%% + w.write(R"(%%% %% interface %% {% } @@ -5835,6 +5866,7 @@ IInspectableVftbl = global::WinRT.IInspectable.Vftbl.AbiToProjectionVftable, // Interface bind(type), bind(type), + bind(type), bind(type, false), is_exclusive_to(type) || (is_projection_internal(type) || (settings.internal || settings.embedded)) ? "internal" : "public", type_name, @@ -6199,7 +6231,7 @@ return global::System.Runtime.InteropServices.CustomQueryInterfaceResult.NotHand auto base_semantics = get_type_semantics(type.Extends()); auto from_abi_new = !std::holds_alternative(base_semantics) ? "new " : ""; - w.write(R"(%[global::WinRT.ProjectedRuntimeClass(typeof(%))] + w.write(R"(%%[global::WinRT.ProjectedRuntimeClass(typeof(%))] %internal %class %% { public %(% comp) @@ -6224,6 +6256,7 @@ private readonly % _comp; } )", bind(type), + bind(type), default_interface_name, bind(type, false), bind(type), @@ -6272,7 +6305,7 @@ private readonly % _comp; gc_pressure_amount = amount == 0 ? 12000 : amount == 1 ? 120000 : 1200000; } - w.write(R"(%[global::WinRT.ProjectedRuntimeClass(nameof(_default))] + w.write(R"(%%[global::WinRT.ProjectedRuntimeClass(nameof(_default))] %% %class %%, IEquatable<%> { public %IntPtr ThisPtr => _default.ThisPtr; @@ -6307,6 +6340,7 @@ private % AsInternal(InterfaceTag<%> _) => _default; } )", bind(type), + bind(type), bind(type, false), internal_accessibility(), bind(type), @@ -6438,8 +6472,8 @@ _defaultLazy = new Lazy<%>(() => GetDefaultReference<%.Vftbl>()); auto default_interface_typedef = for_typedef(w, get_type_semantics(get_default_interface(type)), [&](auto&& iface) { return iface; }); auto is_manually_gen_default_interface = is_manually_generated_iface(default_interface_typedef); - w.write(R"(% -[global::WinRT.ProjectedRuntimeClass(nameof(_default))] + w.write(R"(%% +[global::WinRT.ProjectedRuntimeClass(typeof(%))] [global::WinRT.ObjectReferenceWrapper(nameof(_inner))] %% %class %%, IWinRTObject, IEquatable<%> { @@ -6475,6 +6509,8 @@ private struct InterfaceTag{}; } )", bind(type), + bind(type), + default_interface_name, bind(type, true), internal_accessibility(), bind(type), @@ -6719,9 +6755,10 @@ public static ObjectReferenceValue CreateMarshaler2(% obj) => MarshalInterface<% } method_signature signature{ get_delegate_invoke(type) }; - w.write(R"(%%% delegate % %(%); + w.write(R"(%%%% delegate % %(%); )", bind(type), + bind(type), bind(type, false), internal_accessibility(), bind(signature), @@ -7114,7 +7151,7 @@ global::WinRT.ComWrappersSupport.FindObject<%>(%).Invoke(%) fields.emplace_back(field_info); } - w.write(R"(%%% struct %: IEquatable<%> + w.write(R"(%%%% struct %: IEquatable<%> { % public %(%) @@ -7131,6 +7168,7 @@ public override int GetHashCode() => %; )", // struct bind(type), + bind(type), bind(type, true), internal_accessibility(), name, @@ -7692,4 +7730,31 @@ bind(invokeMethodSig)); typeNameToDefinitionMap[eventTypeCode] = eventClass; } } + + void add_base_type_entry(TypeDef const& classType, concurrency::concurrent_unordered_map& typeNameToBaseTypeMap) + { + writer w(""); + auto base_type = get_type_semantics(classType.Extends()); + bool has_base_type = !std::holds_alternative(base_type); + if (has_base_type) + { + int numChars = (int)strlen("global::"); + auto&& typeName = w.write_temp("%", bind(classType, typedef_name_type::Projected, true)).substr(numChars); + auto&& baseTypeName = w.write_temp("%", bind(base_type, typedef_name_type::Projected, true)).substr(numChars); + typeNameToBaseTypeMap[typeName] = baseTypeName; + } + } + + void write_file_header(writer& w) + { + w.write(R"(//------------------------------------------------------------------------------ +// +// This file was generated by cswinrt.exe version % +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +)", VERSION_STRING); + } } diff --git a/src/cswinrt/main.cpp b/src/cswinrt/main.cpp index 345663a12..f4449b065 100644 --- a/src/cswinrt/main.cpp +++ b/src/cswinrt/main.cpp @@ -174,11 +174,11 @@ Where is one or more of: task_group group; - concurrency::concurrent_unordered_map typeNameToDefinitionMap; + concurrency::concurrent_unordered_map typeNameToEventDefinitionMap, typeNameToBaseTypeMap; bool projectionFileWritten = false; for (auto&& ns_members : c.namespaces()) { - group.add([&ns_members, &componentActivatableClasses, &projectionFileWritten, &typeNameToDefinitionMap] + group.add([&ns_members, &componentActivatableClasses, &projectionFileWritten, &typeNameToEventDefinitionMap, &typeNameToBaseTypeMap] { auto&& [ns, members] = ns_members; std::string_view currentType = ""; @@ -219,13 +219,15 @@ Where is one or more of: else { write_class(w, type); + add_base_type_entry(type, typeNameToBaseTypeMap); } if (settings.component && componentActivatableClasses.count(type) == 1) { write_factory_class(w, type); } } - write_temp_class_event_source_subclass(helperWriter, type, typeNameToDefinitionMap); + + write_temp_class_event_source_subclass(helperWriter, type, typeNameToEventDefinitionMap); break; case category::delegate_type: write_delegate(w, type); @@ -236,7 +238,7 @@ Where is one or more of: break; case category::interface_type: write_interface(w, type); - write_temp_interface_event_source_subclass(helperWriter, type, typeNameToDefinitionMap); + write_temp_interface_event_source_subclass(helperWriter, type, typeNameToEventDefinitionMap); break; case category::struct_type: if (is_api_contract_type(type)) @@ -330,15 +332,7 @@ Where is one or more of: group.add([&componentActivatableClasses, &projectionFileWritten] { writer wm; - wm.write(R"(//------------------------------------------------------------------------------ -// -// This file was generated by cswinrt.exe version % -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ -)", VERSION_STRING); + write_file_header(wm); write_module_activation_factory(wm, componentActivatableClasses); wm.flush_to_file(settings.output_folder / (std::string("WinRT_Module") + ".cs")); projectionFileWritten = true; @@ -346,24 +340,48 @@ Where is one or more of: } group.get(); + writer eventHelperWriter("WinRT"); - eventHelperWriter.write(R"(//------------------------------------------------------------------------------ -// -// This file was generated by cswinrt.exe version % -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ -)", VERSION_STRING); + write_file_header(eventHelperWriter); eventHelperWriter.write("namespace WinRT\n{\n%\n}", bind([&](writer& w) { - for (auto&& [key, value] : typeNameToDefinitionMap) + for (auto&& [key, value] : typeNameToEventDefinitionMap) { w.write("%", value); } })); eventHelperWriter.flush_to_file(settings.output_folder / "WinRTEventHelpers.cs"); + if (!typeNameToBaseTypeMap.empty()) + { + writer baseTypeWriter("WinRT"); + write_file_header(baseTypeWriter); + baseTypeWriter.write(R"(namespace WinRT +{ +internal static class ProjectionTypesInitializer +{ +internal readonly static System.Collections.Generic.Dictionary TypeNameToBaseTypeNameMapping = new System.Collections.Generic.Dictionary(%, System.StringComparer.Ordinal) +{ +% +}; + +[System.Runtime.CompilerServices.ModuleInitializer] +internal static void InitalizeProjectionTypes() +{ +ComWrappersSupport.RegisterProjectionTypeBaseTypeMapping(TypeNameToBaseTypeNameMapping); +} +} +})", + typeNameToBaseTypeMap.size(), + bind([&](writer& w) { + for (auto&& [key, value] : typeNameToBaseTypeMap) + { + w.write(R"(["%"] = "%",)", key, value); + w.write("\n"); + } + })); + baseTypeWriter.flush_to_file(settings.output_folder / "WinRTBaseTypeMappingHelper.cs"); + } + if (projectionFileWritten) { for (auto&& string : strings::base) @@ -373,15 +391,7 @@ Where is one or more of: continue; } writer ws; - ws.write(R"(//------------------------------------------------------------------------------ -// -// This file was generated by cswinrt.exe version % -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ -)", VERSION_STRING); + write_file_header(ws); ws.write(string.value); ws.flush_to_file(settings.output_folder / (std::string(string.name) + ".cs")); } diff --git a/src/cswinrt/strings/WinRT.cs b/src/cswinrt/strings/WinRT.cs index feb564980..52bac92f2 100644 --- a/src/cswinrt/strings/WinRT.cs +++ b/src/cswinrt/strings/WinRT.cs @@ -845,19 +845,19 @@ internal static class InterfaceIIDs } } +#if !NET namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method)] internal sealed class ModuleInitializerAttribute : Attribute { } } +#endif namespace WinRT { internal static class ProjectionInitializer { -#pragma warning disable 0436 [ModuleInitializer] -#pragma warning restore 0436 internal static void InitalizeProjection() { ComWrappersSupport.RegisterProjectionAssembly(typeof(ProjectionInitializer).Assembly); diff --git a/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Controls.Primitives/Microsoft.UI.Xaml.Controls.Primitives.cs b/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Controls.Primitives/Microsoft.UI.Xaml.Controls.Primitives.cs index 3a39fd93e..6fc65bf3a 100644 --- a/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Controls.Primitives/Microsoft.UI.Xaml.Controls.Primitives.cs +++ b/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Controls.Primitives/Microsoft.UI.Xaml.Controls.Primitives.cs @@ -3,7 +3,8 @@ namespace Microsoft.UI.Xaml.Controls.Primitives { using Windows.Foundation; - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Controls.Primitives.GeneratorPosition))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal diff --git a/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media.Animation/Microsoft.UI.Xaml.Media.Animation.cs b/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media.Animation/Microsoft.UI.Xaml.Media.Animation.cs index 8eeb51f6a..f267a9613 100644 --- a/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media.Animation/Microsoft.UI.Xaml.Media.Animation.cs +++ b/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media.Animation/Microsoft.UI.Xaml.Media.Animation.cs @@ -3,7 +3,8 @@ namespace Microsoft.UI.Xaml.Media.Animation { using Windows.Foundation; - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Media.Animation.KeyTime))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal @@ -90,7 +91,8 @@ enum RepeatBehaviorType Forever } - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Media.Animation.RepeatBehavior))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal diff --git a/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media.Media3D/Microsoft.UI.Xaml.Media.Media3D.cs b/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media.Media3D/Microsoft.UI.Xaml.Media.Media3D.cs index 8d1ca129e..88ff2ccd8 100644 --- a/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media.Media3D/Microsoft.UI.Xaml.Media.Media3D.cs +++ b/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media.Media3D/Microsoft.UI.Xaml.Media.Media3D.cs @@ -3,7 +3,8 @@ namespace Microsoft.UI.Xaml.Media.Media3D { using Windows.Foundation; - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Media.Media3D.Matrix3D))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal diff --git a/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media/Microsoft.UI.Xaml.Media.cs b/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media/Microsoft.UI.Xaml.Media.cs index 14a7436b5..e8f91861b 100644 --- a/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media/Microsoft.UI.Xaml.Media.cs +++ b/src/cswinrt/strings/additions/Microsoft.UI.Xaml.Media/Microsoft.UI.Xaml.Media.cs @@ -3,7 +3,8 @@ namespace Microsoft.UI.Xaml.Media { using Windows.Foundation; - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Media.Matrix))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal diff --git a/src/cswinrt/strings/additions/Microsoft.UI.Xaml/Microsoft.UI.Xaml.cs b/src/cswinrt/strings/additions/Microsoft.UI.Xaml/Microsoft.UI.Xaml.cs index c96e1ff61..f901fb1ad 100644 --- a/src/cswinrt/strings/additions/Microsoft.UI.Xaml/Microsoft.UI.Xaml.cs +++ b/src/cswinrt/strings/additions/Microsoft.UI.Xaml/Microsoft.UI.Xaml.cs @@ -3,7 +3,8 @@ namespace Microsoft.UI.Xaml { using Windows.Foundation; - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.CornerRadius))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal @@ -163,7 +164,8 @@ enum GridUnitType Star, } - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.GridLength))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal @@ -280,7 +282,8 @@ internal string ToString(global::System.Globalization.CultureInfo cultureInfo) } } - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Thickness))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal @@ -406,7 +409,8 @@ enum DurationType Forever } - [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeType("Microsoft.UI")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Duration))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal diff --git a/src/cswinrt/strings/additions/Windows.Storage.Streams/IBufferByteAccess.cs b/src/cswinrt/strings/additions/Windows.Storage.Streams/IBufferByteAccess.cs index 2b86bac62..9cccb23a2 100644 --- a/src/cswinrt/strings/additions/Windows.Storage.Streams/IBufferByteAccess.cs +++ b/src/cswinrt/strings/additions/Windows.Storage.Streams/IBufferByteAccess.cs @@ -3,7 +3,8 @@ namespace Windows.Storage.Streams using global::System; [global::WinRT.WindowsRuntimeType("Windows.Foundation.UniversalApiContract")] - [Guid("905a0fef-bc53-11df-8c49-001e4fc686da")] + [Guid("905a0fef-bc53-11df-8c49-001e4fc686da")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Windows.Storage.Streams.IBufferByteAccess))] internal interface IBufferByteAccess { IntPtr Buffer { get; } diff --git a/src/cswinrt/strings/additions/Windows.Storage.Streams/IMarshal.cs b/src/cswinrt/strings/additions/Windows.Storage.Streams/IMarshal.cs index 47d7a3834..6af6c0586 100644 --- a/src/cswinrt/strings/additions/Windows.Storage.Streams/IMarshal.cs +++ b/src/cswinrt/strings/additions/Windows.Storage.Streams/IMarshal.cs @@ -6,7 +6,8 @@ internal enum MSHCTX : int { Local = 0, NoSharedMem = 1, DifferentMachine = 2, I internal enum MSHLFLAGS : int { Normal = 0, TableStrong = 1, TableWeak = 2, NoPing = 4 } [global::WinRT.WindowsRuntimeType("Windows.Foundation.UniversalApiContract")] - [Guid("00000003-0000-0000-c000-000000000046")] + [Guid("00000003-0000-0000-c000-000000000046")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Com.IMarshal))] internal interface IMarshal { unsafe void GetUnmarshalClass(Guid* riid, IntPtr pv, MSHCTX dwDestContext, IntPtr pvDestContext, MSHLFLAGS mshlFlags, Guid* pCid); diff --git a/src/cswinrt/strings/additions/Windows.Storage/IStorageFolderHandleAccess.cs b/src/cswinrt/strings/additions/Windows.Storage/IStorageFolderHandleAccess.cs index 6d53313de..2b9f841a1 100644 --- a/src/cswinrt/strings/additions/Windows.Storage/IStorageFolderHandleAccess.cs +++ b/src/cswinrt/strings/additions/Windows.Storage/IStorageFolderHandleAccess.cs @@ -7,7 +7,8 @@ namespace Windows.Storage { using Microsoft.Win32.SafeHandles; // Available in 14393 (RS1) and later - [Guid("DF19938F-5462-48A0-BE65-D2A3271A08D6")] + [Guid("DF19938F-5462-48A0-BE65-D2A3271A08D6")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Windows.Storage.IStorageFolderHandleAccess))] internal interface IStorageFolderHandleAccess { SafeFileHandle Create( diff --git a/src/cswinrt/strings/additions/Windows.Storage/IStorageItemHandleAccess.cs b/src/cswinrt/strings/additions/Windows.Storage/IStorageItemHandleAccess.cs index a797f91f2..ecd1bab08 100644 --- a/src/cswinrt/strings/additions/Windows.Storage/IStorageItemHandleAccess.cs +++ b/src/cswinrt/strings/additions/Windows.Storage/IStorageItemHandleAccess.cs @@ -6,7 +6,8 @@ namespace Windows.Storage { using Microsoft.Win32.SafeHandles; // Available in 14393 (RS1) and later - [Guid("5CA296B2-2C25-4D22-B785-B885C8201E6A")] + [Guid("5CA296B2-2C25-4D22-B785-B885C8201E6A")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Windows.Storage.IStorageItemHandleAccess))] internal interface IStorageItemHandleAccess { SafeFileHandle Create( diff --git a/src/cswinrt/strings/additions/Windows.UI/Windows.UI.cs b/src/cswinrt/strings/additions/Windows.UI/Windows.UI.cs index 913b030a4..001598028 100644 --- a/src/cswinrt/strings/additions/Windows.UI/Windows.UI.cs +++ b/src/cswinrt/strings/additions/Windows.UI/Windows.UI.cs @@ -4,7 +4,8 @@ namespace Windows.UI using global::System; using global::System.Globalization; - [global::WinRT.WindowsRuntimeType("Windows.Foundation.UniversalApiContract")] + [global::WinRT.WindowsRuntimeType("Windows.Foundation.UniversalApiContract")] + [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Windows.UI.Color))] [StructLayout(LayoutKind.Sequential)] #if EMBED internal