Skip to content

Commit

Permalink
Merge pull request #1110 from microsoft/fix968
Browse files Browse the repository at this point in the history
Emit `DllImportAttribute.EntryPoint` when metadata sets it to a custom value
  • Loading branch information
AArnott committed Jan 10, 2024
2 parents efd80a7 + 1d5d0ff commit e54bb73
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/Microsoft.Windows.CsWin32/Generator.Extern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ private void DeclareExternMethod(MethodDefinitionHandle methodDefinitionHandle)
methodName = newName;
}

if (!import.Name.IsNil && import.Name != methodDefinition.Name)
{
entrypoint = this.Reader.GetString(import.Name);
}

// If this method releases a handle, recreate the method signature such that we take the struct rather than the SafeHandle as a parameter.
TypeSyntaxSettings typeSettings = this.MetadataIndex.ReleaseMethods.Contains(entrypoint ?? methodName) ? this.externReleaseSignatureTypeSettings : this.externSignatureTypeSettings;
MethodSignature<TypeHandleInfo> signature = methodDefinition.DecodeSignature(SignatureHandleProvider.Instance, null);
Expand Down
23 changes: 22 additions & 1 deletion test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,31 @@ public void SetLastError_ByMarshaling(
AttributeSyntax? attribute = FindDllImportAttribute(originalMethod.AttributeLists) ?? FindDllImportAttribute(originalMethod.Body?.Statements.OfType<LocalFunctionStatementSyntax>().SingleOrDefault()?.AttributeLists ?? default);
Assert.NotNull(attribute);
Assert.Equal(expectMarshalingAttribute, attribute.ArgumentList!.Arguments.Any(a => a.NameEquals?.Name.Identifier.ValueText == "SetLastError"));
}

[Fact]
public void CustomEntryPointCarriesOver()
{
this.GenerateApi("FileIconInit");
MethodDeclarationSyntax method = Assert.Single(this.FindGeneratedMethod("FileIconInit"));
AttributeSyntax? attribute = FindDllImportAttribute(method.AttributeLists);
Assert.NotNull(attribute);
AttributeArgumentSyntax arg = Assert.Single(attribute.ArgumentList!.Arguments, a => a.NameEquals?.Name.Identifier.ValueText == "EntryPoint");
Assert.True(arg.Expression is LiteralExpressionSyntax { RawKind: (int)SyntaxKind.StringLiteralExpression, Token: { Value: "#660" } });
}

static AttributeSyntax? FindDllImportAttribute(SyntaxList<AttributeListSyntax> attributeLists) => attributeLists.SelectMany(al => al.Attributes).FirstOrDefault(a => a.Name.ToString() == "DllImport");
[Fact]
public void DefaultEntryPointIsNotEmitted()
{
this.GenerateApi("GetTickCount");
MethodDeclarationSyntax method = Assert.Single(this.FindGeneratedMethod("GetTickCount"));
AttributeSyntax? attribute = FindDllImportAttribute(method.AttributeLists);
Assert.NotNull(attribute);
Assert.DoesNotContain(attribute.ArgumentList!.Arguments, a => a.NameEquals?.Name.Identifier.ValueText == "EntryPoint");
}

private static AttributeSyntax? FindDllImportAttribute(SyntaxList<AttributeListSyntax> attributeLists) => attributeLists.SelectMany(al => al.Attributes).FirstOrDefault(a => a.Name.ToString() == "DllImport");

private IEnumerable<MethodDeclarationSyntax> GenerateMethod(string methodName)
{
this.GenerateApi(methodName);
Expand Down

0 comments on commit e54bb73

Please sign in to comment.