Skip to content

Commit 7995bb2

Browse files
authored
Add implicit IntPtr casts to void* typedefs (#1521)
* Add regression test * Add helpers for void* typedefs
1 parent 3a17ab0 commit 7995bb2

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

src/Microsoft.Windows.CsWin32/Generator.TypeDef.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,35 @@ private StructDeclarationSyntax DeclareTypeDefStruct(TypeDefinition typeDef, Typ
173173
.WithSemicolonToken(SemicolonWithLineFeed));
174174
}
175175
}
176+
else if (fieldInfo.FieldType is PointerTypeSyntax pts && IsVoid(pts.ElementType))
177+
{
178+
// void* typedefs should still get IntPtr conversions for convenience like their HANDLE counterparts.
179+
180+
// public static implicit operator IntPtr(PSID value) => new IntPtr(value.Value);
181+
ExpressionSyntax valueValueArg = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, valueParameter, fieldIdentifierName);
182+
members = members.Add(ConversionOperatorDeclaration(Token(SyntaxKind.ImplicitKeyword), IntPtrTypeSyntax)
183+
.AddParameterListParameters(Parameter(valueParameter.Identifier).WithType(name.WithTrailingTrivia(TriviaList(Space))))
184+
.WithExpressionBody(ArrowExpressionClause(
185+
ObjectCreationExpression(IntPtrTypeSyntax).AddArgumentListArguments(Argument(valueValueArg))))
186+
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword)) // operators MUST be public
187+
.WithSemicolonToken(SemicolonWithLineFeed));
188+
189+
// public static explicit operator PSID(IntPtr value) => new PSID(value.ToPointer());
190+
members = members.Add(ConversionOperatorDeclaration(Token(SyntaxKind.ExplicitKeyword), name)
191+
.AddParameterListParameters(Parameter(valueParameter.Identifier).WithType(IntPtrTypeSyntax.WithTrailingTrivia(TriviaList(Space))))
192+
.WithExpressionBody(ArrowExpressionClause(ObjectCreationExpression(name).AddArgumentListArguments(
193+
Argument(CastExpression(fieldInfo.FieldType, InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, valueParameter, IdentifierName(nameof(IntPtr.ToPointer)))))))))
194+
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword)) // operators MUST be public
195+
.WithSemicolonToken(SemicolonWithLineFeed));
196+
197+
// public static explicit operator PSID(UIntPtr value) => new PSID(value.ToPointer());
198+
members = members.Add(ConversionOperatorDeclaration(Token(SyntaxKind.ExplicitKeyword), name)
199+
.AddParameterListParameters(Parameter(valueParameter.Identifier).WithType(UIntPtrTypeSyntax.WithTrailingTrivia(TriviaList(Space))))
200+
.WithExpressionBody(ArrowExpressionClause(ObjectCreationExpression(name).AddArgumentListArguments(
201+
Argument(CastExpression(fieldInfo.FieldType, InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, valueParameter, IdentifierName(nameof(IntPtr.ToPointer)))))))))
202+
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword)) // operators MUST be public
203+
.WithSemicolonToken(SemicolonWithLineFeed));
204+
}
176205

177206
foreach (string alsoUsableForValue in this.GetAlsoUsableForValues(typeDef))
178207
{

test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,16 @@ public void ReleaseMethodGeneratedWithUncommonReturnType(string api)
156156
[Theory]
157157
[InlineData("HDC")]
158158
public void InterestingHandles(string api) => this.GenerateApi(api);
159+
160+
[Theory]
161+
[InlineData("HWND")]
162+
[InlineData("PSID")]
163+
public void VerifyHandlesHaveImplicitIntPtrCast(string api)
164+
{
165+
this.GenerateApi(api);
166+
BaseTypeDeclarationSyntax type = Assert.Single(this.FindGeneratedType(api));
167+
IEnumerable<string> methods = type.DescendantNodes().OfType<ConversionOperatorDeclarationSyntax>()
168+
.Select(x => x.Type).OfType<IdentifierNameSyntax>().Select(x => x.Identifier.ValueText);
169+
Assert.Contains("IntPtr", methods);
170+
}
159171
}

0 commit comments

Comments
 (0)