From a6a7d0148b02de6cdea06675d01305659173db61 Mon Sep 17 00:00:00 2001 From: Dongle <29563098+dongle-the-gadget@users.noreply.github.com> Date: Wed, 30 Oct 2024 00:02:58 +0700 Subject: [PATCH 1/3] Initial work. --- src/Tests/AuthoringConsumptionTest/test.cpp | 10 ++++++++++ src/Tests/AuthoringTest/Program.cs | 15 ++++++++++++++- src/WinRT.Runtime/ComWrappersSupport.cs | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Tests/AuthoringConsumptionTest/test.cpp b/src/Tests/AuthoringConsumptionTest/test.cpp index cffdc9a8b..a0d09f117 100644 --- a/src/Tests/AuthoringConsumptionTest/test.cpp +++ b/src/Tests/AuthoringConsumptionTest/test.cpp @@ -683,6 +683,12 @@ TEST(AuthoringTest, MixedWinRTClassicCOM) winrt::com_ptr<::IUnknown> internalInterface2; EXPECT_EQ(unknown2->QueryInterface(internalInterface2Iid, internalInterface2.put_void()), S_OK); + IID internalInterface3Iid; + check_hresult(IIDFromString(L"{6234C2F7-9917-469F-BDB4-3E8C630598AF", &internalInterface3Iid)); + winrt::com_ptr<::IUnknown> unknown3 = wrapper.as<::IUnknown>(); + winrt::com_ptr<::IUnknown> internalInterface3; + EXPECT_EQ(unknown3->QueryInterface(internalInterface3Iid, internalInterface3.put_void()), S_OK); + typedef int (__stdcall* GetNumber)(void*, int*); int number; @@ -694,6 +700,10 @@ TEST(AuthoringTest, MixedWinRTClassicCOM) // Validate the second call on IInternalInterface2 EXPECT_EQ(reinterpret_cast((*reinterpret_cast(internalInterface2.get()))[3])(internalInterface2.get(), &number), S_OK); EXPECT_EQ(number, 123); + + // Validate the third call on IInternalInterface3 + EXPECT_EQ(reinterpret_cast((*reinterpret_cast(internalInterface3.get()))[3])(internalInterface3.get(), &number), S_OK); + EXPECT_EQ(number, 1); } TEST(AuthoringTest, GetRuntimeClassName) diff --git a/src/Tests/AuthoringTest/Program.cs b/src/Tests/AuthoringTest/Program.cs index 183d65228..4b92c86bc 100644 --- a/src/Tests/AuthoringTest/Program.cs +++ b/src/Tests/AuthoringTest/Program.cs @@ -1804,7 +1804,8 @@ public void Dispose() } } - public sealed class TestMixedWinRTCOMWrapper : IGraphicsEffectSource, IPublicInterface, IInternalInterface1, SomeInternalType.IInternalInterface2 + [System.Runtime.InteropServices.Marshalling.GeneratedComClass] + public sealed partial class TestMixedWinRTCOMWrapper : IGraphicsEffectSource, IPublicInterface, IInternalInterface1, SomeInternalType.IInternalInterface2, IInternalInterface3 { public string HelloWorld() { @@ -1824,6 +1825,11 @@ unsafe int SomeInternalType.IInternalInterface2.GetNumber(int* value) return 0; } + + int IInternalInterface3.GetNumber() + { + return 1; + } } public interface IPublicInterface @@ -1920,6 +1926,13 @@ private static int GetNumberFromAbi(void* thisPtr, int* value) } } + [System.Runtime.InteropServices.Guid("6234C2F7-9917-469F-BDB4-3E8C630598AF")] + [System.Runtime.InteropServices.Marshalling.GeneratedComInterface] + internal partial interface IInternalInterface3 + { + int GetNumber(); + } + [System.Runtime.InteropServices.Guid("26D8EE57-8B1B-46F4-A4F9-8C6DEEEAF53A")] public interface ICustomInterfaceGuid { diff --git a/src/WinRT.Runtime/ComWrappersSupport.cs b/src/WinRT.Runtime/ComWrappersSupport.cs index 7ea4e9029..5d72ff088 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.cs @@ -210,6 +210,24 @@ internal static List GetInterfaceTableEntries(Type type) } } +#if NET8_0_OR_GREATER + var comExposedDetails = System.Runtime.InteropServices.Marshalling.StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy.GetComExposedTypeDetails(type.TypeHandle); + + if (comExposedDetails != null) + { + ReadOnlySpan comInterfaceEntries; + unsafe + { + ComInterfaceEntry* entriesPointer = comExposedDetails.GetComInterfaceEntries(out int generatedEntriesCount); + comInterfaceEntries = new ReadOnlySpan(entriesPointer, generatedEntriesCount); + } + foreach (var entry in comInterfaceEntries) + { + entries.Add(entry); + } + } +#endif + if (winrtExposedClassAttribute != null) { hasWinrtExposedClassAttribute = true; From ba546814b82d1cad73dcb7a10fba3aeadd01fadf Mon Sep 17 00:00:00 2001 From: Dongle <29563098+dongle-the-gadget@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:14:45 +0700 Subject: [PATCH 2/3] Finalize GeneratedComClass prototype. --- .../WinRT.SourceGenerator/WinRTTypeWriter.cs | 15 ++++++++++++++- src/Tests/AuthoringConsumptionTest/test.cpp | 3 ++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs b/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs index 65cad7823..80f4ef050 100644 --- a/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs +++ b/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs @@ -2718,7 +2718,20 @@ bool IsWinRTType(ISymbol symbol, TypeMapper mapper) { // Interfaces which are allowed to be implemented on authored types but // aren't WinRT interfaces. - return !ImplementedInterfacesWithoutMapping.Contains(QualifiedName(namedType)); + bool isMapped = ImplementedInterfacesWithoutMapping.Contains(QualifiedName(namedType)); + + if (isMapped) + return false; + + // If the interface is publicly accessible, it is a WinRT interface. + bool isPublic = namedType.IsPubliclyAccessible(); + + if (isPublic) + return true; + + // If it's not a publicly accessible interface, it's a WinRT interface if it has the + // [WindowsRuntimeType] attribute. + return namedType.GetAttributes().Any(static attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeTypeAttribute") == 0); } return namedType.SpecialType != SpecialType.System_Object && diff --git a/src/Tests/AuthoringConsumptionTest/test.cpp b/src/Tests/AuthoringConsumptionTest/test.cpp index a0d09f117..f6722ce40 100644 --- a/src/Tests/AuthoringConsumptionTest/test.cpp +++ b/src/Tests/AuthoringConsumptionTest/test.cpp @@ -683,8 +683,9 @@ TEST(AuthoringTest, MixedWinRTClassicCOM) winrt::com_ptr<::IUnknown> internalInterface2; EXPECT_EQ(unknown2->QueryInterface(internalInterface2Iid, internalInterface2.put_void()), S_OK); + // Verify we can grab the generated COM interface IID internalInterface3Iid; - check_hresult(IIDFromString(L"{6234C2F7-9917-469F-BDB4-3E8C630598AF", &internalInterface3Iid)); + check_hresult(IIDFromString(L"{6234C2F7-9917-469F-BDB4-3E8C630598AF}", &internalInterface3Iid)); winrt::com_ptr<::IUnknown> unknown3 = wrapper.as<::IUnknown>(); winrt::com_ptr<::IUnknown> internalInterface3; EXPECT_EQ(unknown3->QueryInterface(internalInterface3Iid, internalInterface3.put_void()), S_OK); From e1e5e28cf33cc4182e11ba6765efc2144753c9f7 Mon Sep 17 00:00:00 2001 From: Dongle <29563098+dongle-the-gadget@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:18:32 +0700 Subject: [PATCH 3/3] Fix indentation --- src/Tests/AuthoringConsumptionTest/test.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Tests/AuthoringConsumptionTest/test.cpp b/src/Tests/AuthoringConsumptionTest/test.cpp index f6722ce40..0234480df 100644 --- a/src/Tests/AuthoringConsumptionTest/test.cpp +++ b/src/Tests/AuthoringConsumptionTest/test.cpp @@ -685,10 +685,10 @@ TEST(AuthoringTest, MixedWinRTClassicCOM) // Verify we can grab the generated COM interface IID internalInterface3Iid; - check_hresult(IIDFromString(L"{6234C2F7-9917-469F-BDB4-3E8C630598AF}", &internalInterface3Iid)); - winrt::com_ptr<::IUnknown> unknown3 = wrapper.as<::IUnknown>(); - winrt::com_ptr<::IUnknown> internalInterface3; - EXPECT_EQ(unknown3->QueryInterface(internalInterface3Iid, internalInterface3.put_void()), S_OK); + check_hresult(IIDFromString(L"{6234C2F7-9917-469F-BDB4-3E8C630598AF}", &internalInterface3Iid)); + winrt::com_ptr<::IUnknown> unknown3 = wrapper.as<::IUnknown>(); + winrt::com_ptr<::IUnknown> internalInterface3; + EXPECT_EQ(unknown3->QueryInterface(internalInterface3Iid, internalInterface3.put_void()), S_OK); typedef int (__stdcall* GetNumber)(void*, int*); @@ -702,9 +702,9 @@ TEST(AuthoringTest, MixedWinRTClassicCOM) EXPECT_EQ(reinterpret_cast((*reinterpret_cast(internalInterface2.get()))[3])(internalInterface2.get(), &number), S_OK); EXPECT_EQ(number, 123); - // Validate the third call on IInternalInterface3 - EXPECT_EQ(reinterpret_cast((*reinterpret_cast(internalInterface3.get()))[3])(internalInterface3.get(), &number), S_OK); - EXPECT_EQ(number, 1); + // Validate the third call on IInternalInterface3 + EXPECT_EQ(reinterpret_cast((*reinterpret_cast(internalInterface3.get()))[3])(internalInterface3.get(), &number), S_OK); + EXPECT_EQ(number, 1); } TEST(AuthoringTest, GetRuntimeClassName) @@ -782,4 +782,4 @@ TEST(AuthoringTest, ExplicitlyImplementedICustomPropertyProvider) auto propertyValue = customProperty.GetValue(nullptr); EXPECT_EQ(winrt::unbox_value(propertyValue), L"TestPropertyValue"); -} \ No newline at end of file +}