diff --git a/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs b/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs index 3ed2c876..82a7ebdc 100644 --- a/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs +++ b/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs @@ -17,7 +17,7 @@ internal record ArrayTypeHandleInfo(TypeHandleInfo ElementType, ArrayShape Shape internal override TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs, CustomAttributeHandleCollection? customAttributes, ParameterAttributes parameterAttributes) { TypeSyntaxAndMarshaling element = this.ElementType.ToTypeSyntax(inputs, customAttributes); - if (inputs.AllowMarshaling) + if (inputs.AllowMarshaling || inputs.IsField) { ArrayTypeSyntax arrayType = ArrayType(element.Type, SingletonList(ArrayRankSpecifier().AddSizes(this.Shape.Sizes.Select(size => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size))).ToArray()))); MarshalAsAttribute? marshalAs = element.MarshalAsAttribute is object ? new MarshalAsAttribute(UnmanagedType.LPArray) { ArraySubType = element.MarshalAsAttribute.Value } : null; diff --git a/src/Microsoft.Windows.CsWin32/Generator.cs b/src/Microsoft.Windows.CsWin32/Generator.cs index 1c0dad93..335be3dc 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.cs @@ -389,7 +389,7 @@ public Generator(string metadataLibraryPath, Docs? docs, GeneratorOptions option PreferMarshaledTypes: false, AllowMarshaling: options.AllowMarshaling, QualifyNames: false); - this.fieldTypeSettings = this.generalTypeSettings with { QualifyNames = true }; + this.fieldTypeSettings = this.generalTypeSettings with { QualifyNames = true, IsField = true }; this.delegateSignatureTypeSettings = this.generalTypeSettings with { QualifyNames = true }; this.enumTypeSettings = this.generalTypeSettings; this.fieldOfHandleTypeDefTypeSettings = this.generalTypeSettings with { PreferNativeInt = false }; @@ -5324,7 +5324,21 @@ private ParameterSyntax CreateParameter(TypeHandleInfo parameterInfo, Parameter IdentifierNameSyntax indexParamName = IdentifierName("index"); IdentifierNameSyntax p0 = IdentifierName("p0"); IdentifierNameSyntax atThis = IdentifierName("@this"); - TypeSyntax qualifiedElementType = elementType == IntPtrTypeSyntax ? elementType : ((ArrayTypeSyntax)fieldTypeHandleInfo.ToTypeSyntax(this.extensionMethodSignatureTypeSettings, customAttributes).Type).ElementType; + TypeSyntax qualifiedElementType; + if (elementType == IntPtrTypeSyntax) + { + qualifiedElementType = elementType; + } + else + { + qualifiedElementType = fieldTypeHandleInfo.ToTypeSyntax(this.extensionMethodSignatureTypeSettings, customAttributes).Type switch + { + ArrayTypeSyntax at => at.ElementType, + PointerTypeSyntax ptrType => ptrType.ElementType, + _ => throw new GenerationFailedException($"Unexpected runtime type."), + }; + } + TypeSyntaxSettings extensionMethodSignatureTypeSettings = context.Filter(this.extensionMethodSignatureTypeSettings); ////internal static unsafe ref readonly uint ReadOnlyItemRef(this in MainAVIHeader.__dwReserved_4 @this, int index) diff --git a/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs b/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs index a31a13c8..3395ded8 100644 --- a/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs +++ b/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs @@ -3,6 +3,6 @@ namespace Microsoft.Windows.CsWin32; -internal record TypeSyntaxSettings(Generator? Generator, bool PreferNativeInt, bool PreferMarshaledTypes, bool AllowMarshaling, bool QualifyNames) +internal record TypeSyntaxSettings(Generator? Generator, bool PreferNativeInt, bool PreferMarshaledTypes, bool AllowMarshaling, bool QualifyNames, bool IsField = false) { } diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs index 70ed74ab..3b7c9866 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs @@ -1397,6 +1397,20 @@ internal static partial class InlineArrayIndexerExtensions this.AssertGeneratedType("MainAVIHeader", expected, expectedIndexer); } + [Theory, PairwiseData] + public void FixedLengthInlineArrayIn_MODULEENTRY32(bool allowMarshaling) + { + this.generator = this.CreateGenerator(new GeneratorOptions { AllowMarshaling = allowMarshaling }); + Assert.True(this.generator.TryGenerate("MODULEENTRY32", CancellationToken.None)); + this.CollectGeneratedCode(this.generator); + this.AssertNoDiagnostics(); + var decl = (StructDeclarationSyntax)Assert.Single(this.FindGeneratedType("MODULEENTRY32")); + var field = this.FindFieldDeclaration(decl, "szModule"); + Assert.True(field.HasValue); + var fieldType = Assert.IsType(field!.Value.Field.Declaration.Type); + Assert.IsType(Assert.Single(this.FindGeneratedType(fieldType.Identifier.ValueText))); + } + [Fact] public void InOutPWSTRGetsRefSpanCharFriendlyOverload() {