Skip to content

Commit

Permalink
Add special handling for a few more release methods
Browse files Browse the repository at this point in the history
  • Loading branch information
AArnott committed May 9, 2024
1 parent defa2a4 commit af68891
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/Microsoft.Windows.CsWin32/Generator.Handle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ public partial class Generator
IdentifierName(renamedReleaseMethod ?? releaseMethod)),
ArgumentList().AddArguments(releaseHandleArgument));
BlockSyntax? releaseBlock = null;
bool releaseMethodIsUnsafe = false;
if (!(releaseMethodReturnType.Type is PredefinedTypeSyntax { Keyword: { RawKind: (int)SyntaxKind.BoolKeyword } } ||
releaseMethodReturnType.Type is QualifiedNameSyntax { Right: { Identifier: { ValueText: "BOOL" } } }))
{
Expand Down Expand Up @@ -197,6 +198,15 @@ public partial class Generator
ExpressionSyntax noerror = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ParseName("global::Windows.Win32.Foundation.WIN32_ERROR"), IdentifierName("NO_ERROR"));
releaseInvocation = BinaryExpression(SyntaxKind.EqualsExpression, releaseInvocation, noerror);
break;
case "CONFIGRET":
noerror = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ParseName("global::Windows.Win32.Devices.DeviceAndDriverInstallation.CONFIGRET"), IdentifierName("CR_SUCCESS"));
releaseInvocation = BinaryExpression(SyntaxKind.EqualsExpression, releaseInvocation, noerror);
break;
case "LRESULT" when releaseMethod == "ICClose":
this.TryGenerateConstantOrThrow("ICERR_OK");
noerror = CastExpression(ParseName("global::Windows.Win32.Foundation.LRESULT"), MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("PInvoke"), IdentifierName("ICERR_OK")));
releaseInvocation = BinaryExpression(SyntaxKind.EqualsExpression, releaseInvocation, noerror);
break;
case "HGLOBAL":
case "HLOCAL":
releaseInvocation = BinaryExpression(SyntaxKind.EqualsExpression, releaseInvocation, DefaultExpression(releaseMethodReturnType.Type));
Expand All @@ -205,12 +215,29 @@ public partial class Generator
throw new NotSupportedException($"Return type {identifierName.Identifier.ValueText} on release method {releaseMethod} not supported.");
}

break;
case PointerTypeSyntax { ElementType: PredefinedTypeSyntax elementType }:
releaseMethodIsUnsafe = true;
switch (elementType.Keyword.Kind())
{
case SyntaxKind.VoidKeyword when releaseMethod == "FreeSid":
releaseInvocation = BinaryExpression(SyntaxKind.EqualsExpression, releaseInvocation, LiteralExpression(SyntaxKind.NullLiteralExpression));
break;
default:
throw new NotSupportedException($"Return type {elementType}* on release method {releaseMethod} not supported.");
}

break;
}
}

MethodDeclarationSyntax releaseHandleDeclaration = MethodDeclaration(PredefinedType(TokenWithSpace(SyntaxKind.BoolKeyword)), Identifier("ReleaseHandle"))
.AddModifiers(TokenWithSpace(SyntaxKind.ProtectedKeyword), TokenWithSpace(SyntaxKind.OverrideKeyword));
if (releaseMethodIsUnsafe)
{
releaseHandleDeclaration = releaseHandleDeclaration.AddModifiers(TokenWithSpace(SyntaxKind.UnsafeKeyword));
}

releaseHandleDeclaration = releaseBlock is null
? releaseHandleDeclaration
.WithExpressionBody(ArrowExpressionClause(releaseInvocation))
Expand Down
9 changes: 9 additions & 0 deletions test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,13 @@ public void ReleaseMethodGeneratedWithHandleStruct()
this.GenerateApi("HANDLE");
Assert.True(this.IsMethodGenerated("CloseHandle"));
}

[Theory]
[InlineData("ICOpen")]
[InlineData("CM_Register_Notification")]
[InlineData("AllocateAndInitializeSid")]
public void ReleaseMethodGeneratedWithUncommonReturnType(string api)
{
this.GenerateApi(api);
}
}

0 comments on commit af68891

Please sign in to comment.