Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for GeneratedComClassAttribute on WinRT classes #1858

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2726,7 +2726,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 &&
Expand Down
11 changes: 11 additions & 0 deletions src/Tests/AuthoringConsumptionTest/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,13 @@ 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));
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;
Expand All @@ -694,6 +701,10 @@ TEST(AuthoringTest, MixedWinRTClassicCOM)
// Validate the second call on IInternalInterface2
EXPECT_EQ(reinterpret_cast<GetNumber>((*reinterpret_cast<void***>(internalInterface2.get()))[3])(internalInterface2.get(), &number), S_OK);
EXPECT_EQ(number, 123);

// Validate the third call on IInternalInterface3
EXPECT_EQ(reinterpret_cast<GetNumber>((*reinterpret_cast<void***>(internalInterface3.get()))[3])(internalInterface3.get(), &number), S_OK);
EXPECT_EQ(number, 1);
}

TEST(AuthoringTest, GetRuntimeClassName)
Expand Down
15 changes: 14 additions & 1 deletion src/Tests/AuthoringTest/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1837,7 +1837,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()
{
Expand All @@ -1857,6 +1858,11 @@ unsafe int SomeInternalType.IInternalInterface2.GetNumber(int* value)

return 0;
}

int IInternalInterface3.GetNumber()
{
return 1;
}
}

public interface IPublicInterface
Expand Down Expand Up @@ -1953,6 +1959,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
{
Expand Down
18 changes: 18 additions & 0 deletions src/WinRT.Runtime/ComWrappersSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,24 @@ internal static List<ComInterfaceEntry> GetInterfaceTableEntries(Type type)
}
}

#if NET8_0_OR_GREATER
var comExposedDetails = System.Runtime.InteropServices.Marshalling.StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy.GetComExposedTypeDetails(type.TypeHandle);

if (comExposedDetails != null)
{
ReadOnlySpan<ComInterfaceEntry> comInterfaceEntries;
unsafe
{
ComInterfaceEntry* entriesPointer = comExposedDetails.GetComInterfaceEntries(out int generatedEntriesCount);
comInterfaceEntries = new ReadOnlySpan<ComInterfaceEntry>(entriesPointer, generatedEntriesCount);
}
foreach (var entry in comInterfaceEntries)
{
entries.Add(entry);
}
}
#endif

if (winrtExposedClassAttribute != null)
{
hasWinrtExposedClassAttribute = true;
Expand Down