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 a static readonly Guid field to COM structs #712

Merged
merged 1 commit into from
Oct 8, 2022
Merged
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
60 changes: 36 additions & 24 deletions src/Microsoft.Windows.CsWin32/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2598,6 +2598,23 @@ private static bool IsLibraryAllowedAppLocal(string libraryName)
return false;
}

private static Guid DecodeGuidFromAttribute(CustomAttribute guidAttribute)
{
CustomAttributeValue<TypeSyntax> args = guidAttribute.DecodeValue(CustomAttributeTypeProvider.Instance);
return new Guid(
(uint)args.FixedArguments[0].Value!,
(ushort)args.FixedArguments[1].Value!,
(ushort)args.FixedArguments[2].Value!,
(byte)args.FixedArguments[3].Value!,
(byte)args.FixedArguments[4].Value!,
(byte)args.FixedArguments[5].Value!,
(byte)args.FixedArguments[6].Value!,
(byte)args.FixedArguments[7].Value!,
(byte)args.FixedArguments[8].Value!,
(byte)args.FixedArguments[9].Value!,
(byte)args.FixedArguments[10].Value!);
}

private T AddApiDocumentation<T>(string api, T memberDeclaration)
where T : MemberDeclarationSyntax
{
Expand Down Expand Up @@ -3522,13 +3539,27 @@ private TypeDeclarationSyntax DeclareInterfaceAsStruct(TypeDefinitionHandle type
// private void** lpVtbl; // Vtbl* (but we avoid strong typing to enable trimming the entire vtbl struct away)
members.Add(FieldDeclaration(VariableDeclaration(PointerType(PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))))).AddVariables(VariableDeclarator(vtblFieldName.Identifier))).AddModifiers(TokenWithSpace(SyntaxKind.PrivateKeyword)));

CustomAttribute? guidAttribute = this.FindGuidAttribute(typeDef.GetCustomAttributes());
Guid? guidAttributeValue = guidAttribute.HasValue ? DecodeGuidFromAttribute(guidAttribute.Value) : null;
if (guidAttribute.HasValue)
{
// internal static readonly Guid Guid = new Guid(0x1234, ...);
TypeSyntax guidTypeSyntax = IdentifierName(nameof(Guid));
members.Add(FieldDeclaration(
VariableDeclaration(guidTypeSyntax)
.AddVariables(VariableDeclarator(Identifier("Guid")).WithInitializer(EqualsValueClause(
GuidValue(guidAttribute.Value)))))
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.ReadOnlyKeyword))
.WithLeadingTrivia(ParseLeadingTrivia($"/// <summary>The IID guid for this interface.</summary>\n/// <value>{guidAttributeValue!.Value:B}</value>\n")));
}

StructDeclarationSyntax iface = StructDeclaration(ifaceName.Identifier)
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.UnsafeKeyword))
.AddMembers(members.ToArray());

if (this.FindGuidFromAttribute(typeDef) is Guid guid)
if (guidAttribute.HasValue)
{
iface = iface.AddAttributeLists(AttributeList().AddAttributes(GUID(guid)));
iface = iface.AddAttributeLists(AttributeList().AddAttributes(GUID(DecodeGuidFromAttribute(guidAttribute.Value))));
}

if (this.GetSupportedOSPlatformAttribute(typeDef.GetCustomAttributes()) is AttributeSyntax supportedOSPlatformAttribute)
Expand Down Expand Up @@ -3704,30 +3735,11 @@ private TypeDeclarationSyntax DeclareInterfaceAsStruct(TypeDefinitionHandle type
return ifaceDeclaration;
}

private Guid? FindGuidFromAttribute(TypeDefinition typeDef) => this.FindGuidFromAttribute(typeDef.GetCustomAttributes());
private CustomAttribute? FindGuidAttribute(CustomAttributeHandleCollection attributes) => this.FindInteropDecorativeAttribute(attributes, nameof(GuidAttribute));

private Guid? FindGuidFromAttribute(CustomAttributeHandleCollection attributes)
{
Guid? guid = null;
if (this.FindInteropDecorativeAttribute(attributes, nameof(GuidAttribute)) is CustomAttribute att)
{
CustomAttributeValue<TypeSyntax> args = att.DecodeValue(CustomAttributeTypeProvider.Instance);
guid = new Guid(
(uint)args.FixedArguments[0].Value!,
(ushort)args.FixedArguments[1].Value!,
(ushort)args.FixedArguments[2].Value!,
(byte)args.FixedArguments[3].Value!,
(byte)args.FixedArguments[4].Value!,
(byte)args.FixedArguments[5].Value!,
(byte)args.FixedArguments[6].Value!,
(byte)args.FixedArguments[7].Value!,
(byte)args.FixedArguments[8].Value!,
(byte)args.FixedArguments[9].Value!,
(byte)args.FixedArguments[10].Value!);
}
private Guid? FindGuidFromAttribute(TypeDefinition typeDef) => this.FindGuidFromAttribute(typeDef.GetCustomAttributes());

return guid;
}
private Guid? FindGuidFromAttribute(CustomAttributeHandleCollection attributes) => this.FindGuidAttribute(attributes) is CustomAttribute att ? (Guid?)DecodeGuidFromAttribute(att) : null;

private DelegateDeclarationSyntax DeclareDelegate(TypeDefinition typeDef)
{
Expand Down