Skip to content

Commit

Permalink
Merge pull request #344 from microsoft/user/sotteson/guid-scraping-an…
Browse files Browse the repository at this point in the history
…d-bugs

User/sotteson/guid scraping and bugs
  • Loading branch information
sotteson1 authored Mar 13, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents fef329c + bfba2d9 commit a480d57
Showing 11 changed files with 353 additions and 85 deletions.
8 changes: 6 additions & 2 deletions generation/emitter/requiredNamespacesForNames.rsp
Original file line number Diff line number Diff line change
@@ -13957,8 +13957,10 @@ SORTIDFROMLCID=Windows.Win32.Intl
SORTVERSIONFROMLCID=Windows.Win32.Intl
SUBLANGID=Windows.Win32.Intl
TEXT=Windows.Win32.Intl
CreateNamedPipeA=Windows.Win32.Ipc
WaitNamedPipeA=Windows.Win32.Ipc
CreateNamedPipeA=Windows.Win32.SystemServices
CreateNamedPipeW=Windows.Win32.SystemServices
WaitNamedPipeA=Windows.Win32.SystemServices
WaitNamedPipeW=Windows.Win32.SystemServices
Icmp6CreateFile=Windows.Win32.IpHelper
Icmp6ParseReplies=Windows.Win32.IpHelper
Icmp6SendEcho2=Windows.Win32.IpHelper
@@ -21269,6 +21271,8 @@ RasDialDlgA=Windows.Win32.RoutingAndRemoteAccessService
RasDialDlgW=Windows.Win32.RoutingAndRemoteAccessService
RasEntryDlgA=Windows.Win32.RoutingAndRemoteAccessService
RasEntryDlgW=Windows.Win32.RoutingAndRemoteAccessService
RASENTRYA=Windows.Win32.RoutingAndRemoteAccessService
RASENTRYW=Windows.Win32.RoutingAndRemoteAccessService
RasPhonebookDlgA=Windows.Win32.RoutingAndRemoteAccessService
RasPhonebookDlgW=Windows.Win32.RoutingAndRemoteAccessService
RasSecurityDialogBegin=Windows.Win32.RoutingAndRemoteAccessService
1 change: 1 addition & 0 deletions generation/scraper/enums.json
Original file line number Diff line number Diff line change
@@ -31121,6 +31121,7 @@
{
"name": "MPR_ET",
"flags": false,
"type": "uint",
"members": [
{
"name": "MPR_ET_None"
69 changes: 69 additions & 0 deletions generation/scraper/manualEnums.json
Original file line number Diff line number Diff line change
@@ -1509,5 +1509,74 @@
"value": "( 1 << (int)CERT_QUERY_FORMAT_TYPE.CERT_QUERY_FORMAT_BINARY)"
}
]
},
{
"name": "Uri_CREATE_FLAGS",
"flags": true,
"autoPopulate":
{
"filter": "Uri_CREATE_",
"header": "urlmon.h"
},
"uses": [
{
"method": "CreateUri",
"parameter": "dwFlags"
}
]
},
{
"name": "MPR_INTERFACE_DIAL_MODE",
"flags": false,
"type": "uint",
"members": [
{
"name": "MPRDM_DialFirst",
"value": "0"
},
{
"name": "MPRDM_DialAll",
"value": "RASENTRY_DIAL_MODE.RASEDM_DialAll"
},
{
"name": "MPRDM_DialAsNeeded",
"value": "RASENTRY_DIAL_MODE.RASEDM_DialAsNeeded"
}
],
"uses": [
{
"struct": "MPR_INTERFACE_3",
"field": "dwDialMode"
},
{
"struct": "MPR_INTERFACE_2",
"field": "dwDialMode"
}
]
},
{
"name": "RASENTRY_DIAL_MODE",
"flags": false,
"type": "uint",
"members": [
{
"name": "RASEDM_DialAll",
"value": "1"
},
{
"name": "RASEDM_DialAsNeeded",
"value": "2"
}
],
"uses": [
{
"struct": "RASENTRYA",
"field": "dwDialMode"
},
{
"struct": "RASENTRYW",
"field": "dwDialMode"
}
]
}
]
105 changes: 96 additions & 9 deletions sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ public class ClangSharpSourceWinmdGenerator
public const string Win32StringType = "Windows.Win32.SystemServices.PSTR";

private const string InteropNamespace = "Windows.Win32.Interop";
private const string ScannedSuffix = "__scanned__";

private static readonly Regex TypeImportRegex = new Regex(@"<(([^,]+),\s*Version=(\d+\.\d+\.\d+\.\d+),\s*Culture=([^,]+),\s*PublicKeyToken=([^>]+))>(\S+)");

@@ -52,6 +53,8 @@ public class ClangSharpSourceWinmdGenerator
private Dictionary<string, AssemblyReferenceHandle> assemblyNamesToRefHandles = new Dictionary<string, AssemblyReferenceHandle>();
private Dictionary<string, ITypeSymbol> nameToSymbols = new Dictionary<string, ITypeSymbol>();
private Dictionary<StructDeclarationSyntax, ISymbol> structNodesToInheritedSymbols = new Dictionary<StructDeclarationSyntax, ISymbol>();
private Dictionary<string, FieldDeclarationSyntax> nameToGuidConstFields = new Dictionary<string, FieldDeclarationSyntax>();
private HashSet<string> structNameWithGuids = new HashSet<string>();

private ClangSharpSourceWinmdGenerator(
CSharpCompilation compilation,
@@ -195,14 +198,26 @@ private static byte[] ConvertKeyToByteArray(string key)
return ret;
}

private void AddDiagnostic(string text)
private static string GetQualifiedName(string @namespace, string name)
{
Console.WriteLine(text);
return $"{@namespace}.{name}";
}

private static string GetQualifiedName(string @namespace, string name)
private static bool HasGuidAttribute(SyntaxList<AttributeListSyntax> attributeLists)
{
return $"{@namespace}.{name}";
bool ret = attributeLists.Any(list => list.Attributes.Any(attr => attr.Name.ToString() == "Windows.Win32.Interop.Guid"));
return ret;
}

private static bool HasPropertyKeyAttribute(SyntaxList<AttributeListSyntax> attributeLists)
{
bool ret = attributeLists.Any(list => list.Attributes.Any(attr => attr.Name.ToString() == "PropertyKey"));
return ret;
}

private void CacheGuidConst(FieldDeclarationSyntax guidFieldNode)
{
this.nameToGuidConstFields[guidFieldNode.Declaration.Variables.First().Identifier.ValueText] = guidFieldNode;
}

private void CacheInterfaceType(StructDeclarationSyntax interfaceNode)
@@ -422,6 +437,28 @@ private void WriteInterfaceDef(StructDeclarationSyntax node)
metadataBuilder.AddInterfaceImplementation(destTypeDefHandle, inheritsFromTypeDef);
}

// If this interface node doesn't have a Guid attribute, see if we can
// match it to a Guid constant
if (!HasGuidAttribute(node.AttributeLists))
{
string iidGuidConstName = $"IID_{name}";
if (!this.nameToGuidConstFields.TryGetValue(iidGuidConstName, out var fieldDeclNode))
{
iidGuidConstName += ScannedSuffix;
this.nameToGuidConstFields.TryGetValue(iidGuidConstName, out fieldDeclNode);
}

if (fieldDeclNode != null)
{
ISymbol fieldSymbol = this.compilation.GetSymbolsWithName(iidGuidConstName).FirstOrDefault();

if (fieldSymbol != null)
{
this.AddCustomAttributes(fieldSymbol, destTypeDefHandle);
}
}
}

this.AddCustomAttributes(node, destTypeDefHandle);
}

@@ -798,22 +835,52 @@ private FieldDefinitionHandle WriteClassFields(ClassDeclarationSyntax node)
var model = this.GetModel(node);
var classSymbol = model.GetDeclaredSymbol(node);
FieldDefinitionHandle firstField = default;

foreach (FieldDeclarationSyntax field in node.Members.Where(m => m is FieldDeclarationSyntax))
{
var fieldVariable = field.Declaration.Variables.First();
IFieldSymbol fieldSymbol = (IFieldSymbol)model.GetDeclaredSymbol(fieldVariable);
string name = fieldSymbol.Name;

FieldAttributes fieldAttributes;

if (!fieldSymbol.IsConst)
{
continue;
fieldAttributes = FieldAttributes.Public | FieldAttributes.Static;

if (!HasGuidAttribute(field.AttributeLists) && !HasPropertyKeyAttribute(field.AttributeLists))
{
continue;
}

if (fieldSymbol.Name.StartsWith("IID_"))
{
continue;
}

if (name.EndsWith(ScannedSuffix))
{
name = name.Substring(0, name.Length - ScannedSuffix.Length);
}

if (name.StartsWith("CLSID_"))
{
string testClassName = name.Substring("CLSID_".Length);
if (this.structNameWithGuids.Contains(testClassName))
{
continue;
}
}
}
else
{
fieldAttributes = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault;
}

var fieldSignature = this.EncodeFieldSignature(className, model, field, out string name);
var fieldSignature = this.EncodeFieldSignature(className, model, field, out _);

var fieldDefinitionHandle =
metadataBuilder.AddFieldDefinition(
FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault,
fieldAttributes,
metadataBuilder.GetOrAddString(name),
metadataBuilder.GetOrAddBlob(fieldSignature));
if (fieldSymbol.HasConstantValue)
@@ -1378,12 +1445,17 @@ private void AddCustomAttributes(IEnumerable<AttributeData> attrs, EntityHandle
}
}

private void AddCustomAttributes(ISymbol symbol, EntityHandle entityHandle)
{
this.AddCustomAttributes(symbol.GetAttributes(), entityHandle);
}

private void AddCustomAttributes(SyntaxNode node, EntityHandle entityHandle)
{
var model = this.GetModel(node);
var symbol = model.GetDeclaredSymbol(node);

this.AddCustomAttributes(symbol.GetAttributes(), entityHandle);
this.AddCustomAttributes(symbol, entityHandle);
}

private ISymbol GetInheritedInterfaceSymbol(StructDeclarationSyntax node)
@@ -1728,10 +1800,25 @@ public InterfaceWalker(ClangSharpSourceWinmdGenerator parent)

public override void VisitStructDeclaration(StructDeclarationSyntax node)
{
base.VisitStructDeclaration(node);

if (this.parent.IsInterfaceDef(node))
{
this.parent.CacheInterfaceType(node);
}

if (HasGuidAttribute(node.AttributeLists))
{
this.parent.structNameWithGuids.Add(node.Identifier.ValueText);
}
}

public override void VisitFieldDeclaration(FieldDeclarationSyntax node)
{
if (node.Modifiers.ToString() == "public static readonly" && node.Declaration.Type.ToString() == "Guid")
{
this.parent.CacheGuidConst(node);
}
}
}

23 changes: 23 additions & 0 deletions sources/ClangSharpSourceToWinmd/EncodeHelpers.cs
Original file line number Diff line number Diff line change
@@ -78,6 +78,11 @@ public static uint ParseHex(string text)
text = text.Substring(2);
}

if (char.ToUpperInvariant(text[text.Length - 1]) == 'L')
{
text = text.Substring(0, text.Length - 1);
}

return uint.Parse(text, System.Globalization.NumberStyles.HexNumber);
}

@@ -280,5 +285,23 @@ public static void FixedArguments(this FixedArgumentsEncoder argumentsEncoder, I
argumentsEncoder.AddArgument().TypedConstant(argument);
}
}

public static AttributeListSyntax ConvertGuidToAttributeList(Guid guid)
{
// Outputs in format: {0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
string formattedGuid = guid.ToString("x");

// Get rid of leading { and trailing }}
formattedGuid = formattedGuid.Substring(1, formattedGuid.Length - 3);
// There's one more { we need to get rid of
formattedGuid = formattedGuid.Replace("{", string.Empty);
string args = $"({formattedGuid})";
return
SyntaxFactory.AttributeList(
SyntaxFactory.SingletonSeparatedList<AttributeSyntax>(
SyntaxFactory.Attribute(
SyntaxFactory.ParseName("Windows.Win32.Interop.Guid"),
SyntaxFactory.ParseAttributeArgumentList(args))));
}
}
}
Loading

0 comments on commit a480d57

Please sign in to comment.