From b9389c932199352520a94a7d32a7afbbde05753b Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 26 Sep 2025 09:28:04 -0700 Subject: [PATCH 1/6] Update win32metadata version --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1e38aaac..cf85bfbe 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ true 2.0.199 - 61.0.15-preview + 64.0.22-preview 0.12.8-experimental 0.1.42-alpha From 8b3356339ff934f5fc6aad5882c5fc1753d9b763 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 26 Sep 2025 13:18:59 -0600 Subject: [PATCH 2/6] Bump the WDK --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index cf85bfbe..44b20a3d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,7 +7,7 @@ 2.0.199 64.0.22-preview - 0.12.8-experimental + 0.13.25-experimental 0.1.42-alpha 4.14.0 From 1efb2ca63ab8f06c569ce34dcddbde24dcdd18d3 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 26 Sep 2025 13:42:27 -0600 Subject: [PATCH 3/6] Update another failing test --- test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs index 8a780ecf..f2da5e2a 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs @@ -625,11 +625,11 @@ public void MultipleEntrypointsToOmittedArchSpecificApis() this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(Platform.AnyCpu)); this.generator = this.CreateGenerator(); - // Request a struct that depends on arch-specific IP6_ADDRESS. - Assert.ThrowsAny(() => this.generator.TryGenerate("DNS_SERVICE_INSTANCE", CancellationToken.None)); + // Request a struct that depends on arch-specific SP_DEVINFO_DATA. + Assert.ThrowsAny(() => this.generator.TryGenerate("SP_PROPSHEETPAGE_REQUEST", CancellationToken.None)); - // Request a struct that depends on DNS_SERVICE_INSTANCE. - Assert.ThrowsAny(() => this.generator.TryGenerate("DNS_SERVICE_REGISTER_REQUEST", CancellationToken.None)); + // Request a method that depends on the same arch-specific struct. + Assert.ThrowsAny(() => this.generator.TryGenerate("SetupDiSetSelectedDevice", CancellationToken.None)); // Verify that no uncompilable code was generated. this.CollectGeneratedCode(this.generator); From b6ed6d08b0655fef92ddf6089dc4657617bf83a8 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Wed, 8 Oct 2025 17:06:06 -0700 Subject: [PATCH 4/6] Revert test update as win32metadata is back to the way it was --- test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs index f2da5e2a..8a780ecf 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs @@ -625,11 +625,11 @@ public void MultipleEntrypointsToOmittedArchSpecificApis() this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(Platform.AnyCpu)); this.generator = this.CreateGenerator(); - // Request a struct that depends on arch-specific SP_DEVINFO_DATA. - Assert.ThrowsAny(() => this.generator.TryGenerate("SP_PROPSHEETPAGE_REQUEST", CancellationToken.None)); + // Request a struct that depends on arch-specific IP6_ADDRESS. + Assert.ThrowsAny(() => this.generator.TryGenerate("DNS_SERVICE_INSTANCE", CancellationToken.None)); - // Request a method that depends on the same arch-specific struct. - Assert.ThrowsAny(() => this.generator.TryGenerate("SetupDiSetSelectedDevice", CancellationToken.None)); + // Request a struct that depends on DNS_SERVICE_INSTANCE. + Assert.ThrowsAny(() => this.generator.TryGenerate("DNS_SERVICE_REGISTER_REQUEST", CancellationToken.None)); // Verify that no uncompilable code was generated. this.CollectGeneratedCode(this.generator); From bb2a60a5685cd0b12bbf82b596fe492b938aca38 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Wed, 8 Oct 2025 17:29:31 -0700 Subject: [PATCH 5/6] Fix IPropertyValue issue --- src/Microsoft.Windows.CsWin32/Generator.Features.cs | 2 ++ src/Microsoft.Windows.CsWin32/Generator.cs | 1 + src/Microsoft.Windows.CsWin32/HandleTypeHandleInfo.cs | 5 +++++ test/Microsoft.Windows.CsWin32.Tests/COMTests.cs | 10 ++++++++++ test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs | 7 +++++-- 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Windows.CsWin32/Generator.Features.cs b/src/Microsoft.Windows.CsWin32/Generator.Features.cs index 3a5f581d..ac7b4b4f 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.Features.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.Features.cs @@ -14,6 +14,7 @@ public partial class Generator private readonly bool canUseUnsafeSkipInit; private readonly bool canUseUnmanagedCallersOnlyAttribute; private readonly bool canUseSetLastPInvokeError; + private readonly bool canUseIPropertyValue; private readonly bool overloadResolutionPriorityAttributePredefined; private readonly bool unscopedRefAttributePredefined; private readonly INamedTypeSymbol? runtimeFeatureClass; @@ -21,6 +22,7 @@ public partial class Generator private readonly bool generateSupportedOSPlatformAttributesOnInterfaces; // only supported on net6.0 (https://github.com/dotnet/runtime/pull/48838) private readonly bool generateDefaultDllImportSearchPathsAttribute; private readonly Dictionary supportedFeatures = new(); + internal bool CanUseIPropertyValue => this.canUseIPropertyValue; private void DeclareOverloadResolutionPriorityAttributeIfNecessary() { diff --git a/src/Microsoft.Windows.CsWin32/Generator.cs b/src/Microsoft.Windows.CsWin32/Generator.cs index a00dec7f..66fd1bda 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.cs @@ -120,6 +120,7 @@ public Generator(string metadataLibraryPath, Docs? docs, IEnumerable add this.comIIDInterfacePredefined = this.FindTypeSymbolIfAlreadyAvailable($"{this.Namespace}.{IComIIDGuidInterfaceName}") is not null; this.getDelegateForFunctionPointerGenericExists = this.compilation?.GetTypeByMetadataName(typeof(Marshal).FullName)?.GetMembers(nameof(Marshal.GetDelegateForFunctionPointer)).Any(m => m is IMethodSymbol { IsGenericMethod: true }) is true; this.generateDefaultDllImportSearchPathsAttribute = this.compilation?.GetTypeByMetadataName(typeof(DefaultDllImportSearchPathsAttribute).FullName) is object; + this.canUseIPropertyValue = this.compilation?.GetTypeByMetadataName("Windows.Foundation.IPropertyValue")?.DeclaredAccessibility == Accessibility.Public; if (this.FindTypeSymbolIfAlreadyAvailable("System.Runtime.Versioning.SupportedOSPlatformAttribute") is { } attribute) { this.generateSupportedOSPlatformAttributes = true; diff --git a/src/Microsoft.Windows.CsWin32/HandleTypeHandleInfo.cs b/src/Microsoft.Windows.CsWin32/HandleTypeHandleInfo.cs index 53b6f8b2..5a91a742 100644 --- a/src/Microsoft.Windows.CsWin32/HandleTypeHandleInfo.cs +++ b/src/Microsoft.Windows.CsWin32/HandleTypeHandleInfo.cs @@ -158,6 +158,11 @@ internal override TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs return new TypeSyntaxAndMarshaling(IdentifierName(specialName)); } } + else if (inputs.Generator?.CanUseIPropertyValue != true && simpleName is "IPropertyValue") + { + marshalAs = new MarshalAsAttribute(UnmanagedType.Interface); + return new TypeSyntaxAndMarshaling(PredefinedType(Token(SyntaxKind.ObjectKeyword)), marshalAs, null); + } else if (TryMarshalAsObject(inputs, simpleName, out marshalAs)) { return new TypeSyntaxAndMarshaling(PredefinedType(Token(SyntaxKind.ObjectKeyword)), marshalAs, null); diff --git a/test/Microsoft.Windows.CsWin32.Tests/COMTests.cs b/test/Microsoft.Windows.CsWin32.Tests/COMTests.cs index 6a9af142..ca8602e2 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/COMTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/COMTests.cs @@ -41,6 +41,16 @@ public void CreateDispatcherQueueController_CreatesWinRTCustomMarshaler() Assert.Single(this.FindGeneratedType(WinRTCustomMarshalerClass)); } + [Fact] + public void IGraphicsEffectD2D1Interop_ProjectsIPropertyValueParameter() + { + this.GenerateApi("IGraphicsEffectD2D1Interop"); + InterfaceDeclarationSyntax iface = (InterfaceDeclarationSyntax)this.FindGeneratedType("IGraphicsEffectD2D1Interop").Single(); + MethodDeclarationSyntax getPropertyMember = (MethodDeclarationSyntax)iface.Members[3]; + ParameterSyntax iPropertyValueParameter = getPropertyMember.ParameterList.Parameters[1]; + Assert.Equal("global::Windows.Foundation.IPropertyValue", iPropertyValueParameter.Type?.ToString()); + } + [Fact] public void IInpectableDerivedInterface() { diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs index 8a780ecf..1670419b 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs @@ -226,8 +226,11 @@ public void InterestingAPIs( "ID3D12Resource", // COM interface with base types "OpenTrace", // the CloseTrace method called by the SafeHandle returns WIN32_ERROR. The handle is ALWAYS 64-bits. "QueryTraceProcessingHandle", // uses a handle that is always 64-bits, even in 32-bit processes - "ID2D1RectangleGeometry")] // COM interface with base types + "ID2D1RectangleGeometry", // COM interface with base types + "IGraphicsEffectD2D1Interop")] // COM interface that refers to C#/WinRT types string api, + [CombinatorialValues("netstandard2.0", "net9.0")] + string tfm, bool allowMarshaling) { var options = DefaultTestGeneratorOptions with @@ -235,7 +238,7 @@ public void InterestingAPIs( WideCharOnly = false, AllowMarshaling = allowMarshaling, }; - this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(Platform.X64)); + this.compilation = this.starterCompilations[tfm].WithOptions(this.compilation.Options.WithPlatform(Platform.X64)); this.generator = this.CreateGenerator(options); Assert.True(this.generator.TryGenerate(api, CancellationToken.None)); this.CollectGeneratedCode(this.generator); From 6696392974e28306cf34cb012570594b2132eb3b Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Wed, 8 Oct 2025 18:07:40 -0700 Subject: [PATCH 6/6] Fix build issues --- src/Microsoft.Windows.CsWin32/Generator.Features.cs | 1 + test/Microsoft.Windows.CsWin32.Tests/MyReferenceAssemblies.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Windows.CsWin32/Generator.Features.cs b/src/Microsoft.Windows.CsWin32/Generator.Features.cs index ac7b4b4f..d89b021a 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.Features.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.Features.cs @@ -22,6 +22,7 @@ public partial class Generator private readonly bool generateSupportedOSPlatformAttributesOnInterfaces; // only supported on net6.0 (https://github.com/dotnet/runtime/pull/48838) private readonly bool generateDefaultDllImportSearchPathsAttribute; private readonly Dictionary supportedFeatures = new(); + internal bool CanUseIPropertyValue => this.canUseIPropertyValue; private void DeclareOverloadResolutionPriorityAttributeIfNecessary() diff --git a/test/Microsoft.Windows.CsWin32.Tests/MyReferenceAssemblies.cs b/test/Microsoft.Windows.CsWin32.Tests/MyReferenceAssemblies.cs index 4a958bd2..e5e27c08 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/MyReferenceAssemblies.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/MyReferenceAssemblies.cs @@ -16,7 +16,7 @@ internal static class MyReferenceAssemblies ]; private static readonly ImmutableArray AdditionalLegacyPackagesNET = [ - new PackageIdentity("Microsoft.Windows.SDK.NET.Ref", "10.0.22621.57"), + new PackageIdentity("Microsoft.Windows.SDK.NET.Ref", "10.0.26100.57"), ]; internal static readonly ReferenceAssemblies NetStandard20 = ReferenceAssemblies.NetStandard.NetStandard20.AddPackages([.. AdditionalLegacyPackagesNetFX, .. AdditionalModernPackages]);