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

Update metadata to 17.0.2-preview #489

Merged
merged 1 commit into from
Jan 25, 2022
Merged
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
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<IncludeSymbols Condition=" '$(DebugType)' != 'embedded' ">true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>

<MetadataVersion>15.0.2-preview</MetadataVersion>
<MetadataVersion>17.0.2-preview</MetadataVersion>
<!-- <DiaMetadataVersion>0.2.185-preview-g7e1e6a442c</DiaMetadataVersion> -->
<ApiDocsVersion>0.1.7-alpha</ApiDocsVersion>
</PropertyGroup>
Expand Down
57 changes: 50 additions & 7 deletions src/Microsoft.Windows.CsWin32/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1388,7 +1388,8 @@ internal void RequestConstant(FieldDefinitionHandle fieldDefHandle)
safeHandleType = safeHandleTypeIdentifier;

MethodSignature<TypeHandleInfo> releaseMethodSignature = releaseMethodDef.DecodeSignature(SignatureHandleProvider.Instance, null);
var releaseMethodParameterType = releaseMethodSignature.ParameterTypes[0].ToTypeSyntax(this.externSignatureTypeSettings, default);
TypeHandleInfo releaseMethodParameterTypeHandleInfo = releaseMethodSignature.ParameterTypes[0];
var releaseMethodParameterType = releaseMethodParameterTypeHandleInfo.ToTypeSyntax(this.externSignatureTypeSettings, default);

// If the release method takes more than one parameter, we can't generate a SafeHandle for it.
if (releaseMethodSignature.RequiredParameterCount != 1)
Expand Down Expand Up @@ -1461,6 +1462,12 @@ internal void RequestConstant(FieldDefinitionHandle fieldDefHandle)
BinaryExpression(SyntaxKind.EqualsExpression, thisHandle, invalidValueFieldName))))
.WithSemicolonToken(SemicolonWithLineFeed));

// (struct)this.handle or (struct)(nuint)(nint)this.handle, as appropriate.
bool isUIntPtr = this.TryGetTypeDefFieldType(releaseMethodParameterTypeHandleInfo, out TypeHandleInfo? typeDefStructFieldType) && typeDefStructFieldType is PrimitiveTypeHandleInfo { PrimitiveTypeCode: PrimitiveTypeCode.UIntPtr };
ArgumentSyntax releaseHandleArgument = Argument(CastExpression(
releaseMethodParameterType.Type,
isUIntPtr ? CastExpression(IdentifierName("nuint"), CastExpression(IdentifierName("nint"), thisHandle)) : thisHandle));

// protected override bool ReleaseHandle() => ReleaseMethod((struct)this.handle);
// Special case release functions based on their return type as follows: (https://github.com/microsoft/win32metadata/issues/25)
// * bool => true is success
Expand All @@ -1472,7 +1479,7 @@ internal void RequestConstant(FieldDefinitionHandle fieldDefHandle)
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName(this.options.ClassName),
IdentifierName(renamedReleaseMethod ?? releaseMethod)),
ArgumentList().AddArguments(Argument(CastExpression(releaseMethodParameterType.Type, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName("handle"))))));
ArgumentList().AddArguments(releaseHandleArgument));
BlockSyntax? releaseBlock = null;
if (!(releaseMethodReturnType.Type is PredefinedTypeSyntax { Keyword: { RawKind: (int)SyntaxKind.BoolKeyword } } ||
releaseMethodReturnType.Type is QualifiedNameSyntax { Right: { Identifier: { ValueText: "BOOL" } } }))
Expand Down Expand Up @@ -1508,11 +1515,6 @@ internal void RequestConstant(FieldDefinitionHandle fieldDefHandle)
case QualifiedNameSyntax { Right: IdentifierNameSyntax identifierName }:
switch (identifierName.Identifier.ValueText)
{
case "LSTATUS":
this.TryGenerateTypeOrThrow("WIN32_ERROR");
ExpressionSyntax errorSuccess = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ParseTypeName("global::Windows.Win32.Foundation.WIN32_ERROR"), IdentifierName("ERROR_SUCCESS"));
releaseInvocation = BinaryExpression(SyntaxKind.EqualsExpression, releaseInvocation, CastExpression(ParseTypeName("global::Windows.Win32.Foundation.LSTATUS"), CastExpression(PredefinedType(TokenWithSpace(SyntaxKind.IntKeyword)), errorSuccess)));
break;
case "NTSTATUS":
this.TryGenerateConstantOrThrow("STATUS_SUCCESS");
ExpressionSyntax statusSuccess = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, this.methodsAndConstantsClassName, IdentifierName("STATUS_SUCCESS"));
Expand Down Expand Up @@ -1555,6 +1557,42 @@ internal void RequestConstant(FieldDefinitionHandle fieldDefHandle)
return safeHandleType;
}

internal bool TryGetTypeDefFieldType(TypeHandleInfo typeDef, [NotNullWhen(true)] out TypeHandleInfo? fieldType)
{
if (typeDef is HandleTypeHandleInfo handle)
{
switch (handle.Handle.Kind)
{
case HandleKind.TypeReference:
if (this.TryGetTypeDefHandle((TypeReferenceHandle)handle.Handle, out TypeDefinitionHandle tdh))
{
return Resolve(tdh, out fieldType);
}

break;
case HandleKind.TypeDefinition:
return Resolve((TypeDefinitionHandle)handle.Handle, out fieldType);
}
}

bool Resolve(TypeDefinitionHandle tdh, [NotNullWhen(true)] out TypeHandleInfo? fieldType)
{
TypeDefinition td = this.Reader.GetTypeDefinition(tdh);
foreach (FieldDefinitionHandle fdh in td.GetFields())
{
FieldDefinition fd = this.Reader.GetFieldDefinition(fdh);
fieldType = fd.DecodeSignature(SignatureHandleProvider.Instance, null);
return true;
}

fieldType = null;
return false;
}

fieldType = default;
return false;
}

internal void GetBaseTypeInfo(TypeDefinition typeDef, out StringHandle baseTypeName, out StringHandle baseTypeNamespace)
{
if (typeDef.BaseType.IsNil)
Expand Down Expand Up @@ -2850,6 +2888,11 @@ private FieldDeclarationSyntax DeclareConstant(FieldDefinitionHandle fieldDefHan
// Cast to IntPtr first, then the actual handle struct.
value = CastExpression(fieldType.Type, CastExpression(IntPtrTypeSyntax, ParenthesizedExpression(value)));
}
else if (fieldType.Type is QualifiedNameSyntax { Right: { Identifier: { ValueText: "PCSTR" } } })
{
value = CastExpression(fieldType.Type, CastExpression(PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))), ParenthesizedExpression(value)));
requiresUnsafe = true;
}
else if (fieldType.Type is QualifiedNameSyntax { Right: { Identifier: { ValueText: "PCWSTR" } } })
{
value = CastExpression(PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), ParenthesizedExpression(value));
Expand Down
2 changes: 1 addition & 1 deletion test/GenerationSandbox.Tests/GeneratedForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ private static void PROC_InSignatureChangedToIntPtr()

private static void RegKeyHandle()
{
LSTATUS status = PInvoke.RegLoadAppKey(string.Empty, out SafeRegistryHandle handle, 0, 0, 0);
WIN32_ERROR status = PInvoke.RegLoadAppKey(string.Empty, out SafeRegistryHandle handle, 0, 0, 0);
}
}
2 changes: 2 additions & 0 deletions test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ public void InterestingAPIs(
"WSAHtons", // A method that references SOCKET (which is typed as UIntPtr) so that a SafeHandle will be generated.
"IDelayedPropertyStoreFactory", // interface inheritance across namespaces
"D3D9ON12_ARGS", // Contains an inline array of IUnknown objects
"NCryptOpenKey", // Generates a SafeHandle based on a UIntPtr
"X509_CERT", // A constant defined as PCSTR
"ID3D12Resource", // COM interface with base types
"ID2D1RectangleGeometry")] // COM interface with base types
string api,
Expand Down