From c2db9164eb77f47bdc581a473a2aaf8d69f5be5f Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 25 May 2023 10:00:12 -0600 Subject: [PATCH] Add the WDK as a default metadata input Closes #895 --- Directory.Packages.props | 2 ++ README.md | 6 +--- .../Microsoft.Windows.CsWin32.csproj | 1 + .../Microsoft.Windows.CsWin32.nuspec | 5 ++++ .../Microsoft.Windows.CsWin32.targets | 11 +++++++- .../DelegateTests.cs | 28 +++++++++++++++++++ .../ExternMethodTests.cs | 13 +++++++++ .../GeneratorTestBase.cs | 5 +++- .../HandleTests.cs | 9 ++++++ .../StructTests.cs | 3 ++ version.json | 2 +- 11 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index ff6f75e7..0946183a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,6 +5,7 @@ true 52.0.65-preview + 0.7.3-experimental 0.1.41-alpha @@ -25,6 +26,7 @@ + diff --git a/README.md b/README.md index b2aa1650..801f7e11 100644 --- a/README.md +++ b/README.md @@ -126,11 +126,7 @@ To update the metadata used as the source for code generation, you may install a dotnet add package Microsoft.Windows.SDK.Win32Metadata --prerelease ``` -Alternatively, you may set the `MicrosoftWindowsSdkWin32MetadataBasePath` property in your project file to the path of the directory containing `Windows.Win32.winmd`: - -```xml -c:\path\to\dir -``` +CsWin32 also consumes the WDK from a similarly named package: `Microsoft.Windows.WDK.WDKMetadata`. ## Consuming daily builds diff --git a/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.csproj b/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.csproj index 6ae664f0..8c10e267 100644 --- a/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.csproj +++ b/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.csproj @@ -48,6 +48,7 @@ + diff --git a/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.nuspec b/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.nuspec index c83c5685..4ca3148a 100644 --- a/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.nuspec +++ b/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.nuspec @@ -17,28 +17,33 @@ + + + + + diff --git a/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.targets b/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.targets index bb04f231..e5bf66de 100644 --- a/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.targets +++ b/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.targets @@ -5,7 +5,16 @@ - $(NuspecProperties);Version=$(Version);BaseOutputPath=$(OutputPath);MetadataVersion=$(MetadataVersion);ApiDocsVersion=$(ApiDocsVersion);PackageReleaseNotes=$(PackageReleaseNotes);commit=$(GitCommitId); + + $(NuspecProperties); + Version=$(Version); + BaseOutputPath=$(OutputPath); + MetadataVersion=$(MetadataVersion); + WDKMetadataVersion=$(WDKMetadataVersion); + ApiDocsVersion=$(ApiDocsVersion); + PackageReleaseNotes=$(PackageReleaseNotes); + commit=$(GitCommitId); + diff --git a/test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs b/test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs new file mode 100644 index 00000000..182c5665 --- /dev/null +++ b/test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +public class DelegateTests : GeneratorTestBase +{ + public DelegateTests(ITestOutputHelper logger) + : base(logger) + { + } + + [Theory] + [CombinatorialData] + public void InterestingDelegates( + [CombinatorialValues( + "LPD3DHAL_RENDERSTATECB")] // A delegate with a pointer parameter to a managed struct. + string name, + bool allowMarshaling) + { + var options = DefaultTestGeneratorOptions with + { + AllowMarshaling = allowMarshaling, + }; + this.generator = this.CreateGenerator(options); + Assert.True(this.generator.TryGenerate(name, CancellationToken.None)); + this.CollectGeneratedCode(this.generator); + this.AssertNoDiagnostics(); + } +} diff --git a/test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs b/test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs index 1691bc6e..8af79bfc 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs @@ -44,4 +44,17 @@ public void AssociatedEnumOnParameterWithVoidReturn() this.CollectGeneratedCode(this.generator); this.AssertNoDiagnostics(); } + + /// + /// Verifies that we can generate APIs from the WDK, which includes references to the SDK. + /// + [Fact] + public void WdkMethod_NtCreateFile() + { + const string Method = "NtCreateFile"; + this.generator = this.CreateGenerator(); + Assert.True(this.generator.TryGenerate(Method, CancellationToken.None)); + this.CollectGeneratedCode(this.generator); + this.AssertNoDiagnostics(); + } } diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs index 654cb610..e26ea4c8 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs @@ -7,6 +7,8 @@ public abstract class GeneratorTestBase : IDisposable, IAsyncLifetime protected static readonly GeneratorOptions DefaultTestGeneratorOptions = new GeneratorOptions { EmitSingleFile = true }; protected static readonly string FileSeparator = new string('=', 140); protected static readonly string MetadataPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location!)!, "Windows.Win32.winmd"); + protected static readonly string WdkMetadataPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location!)!, "Windows.Wdk.winmd"); + protected static readonly string[] DefaultMetadataPaths = new[] { MetadataPath, WdkMetadataPath }; ////protected static readonly string DiaMetadataPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location!)!, "Microsoft.Dia.winmd"); protected static readonly string ApiDocsPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location!)!, "apidocs.msgpack"); @@ -319,7 +321,8 @@ protected async Task CreateCompilationAsync(ReferenceAssembli return compilation; } - protected SuperGenerator CreateGenerator(GeneratorOptions? options = null, CSharpCompilation? compilation = null, bool includeDocs = false) => this.CreateSuperGenerator(new[] { MetadataPath }, options, compilation, includeDocs); + protected SuperGenerator CreateGenerator(GeneratorOptions? options = null, CSharpCompilation? compilation = null, bool includeDocs = false) + => this.CreateSuperGenerator(DefaultMetadataPaths, options, compilation, includeDocs); protected SuperGenerator CreateSuperGenerator(string[] metadataPaths, GeneratorOptions? options = null, CSharpCompilation? compilation = null, bool includeDocs = false) => SuperGenerator.Combine(metadataPaths.Select(path => new Generator(path, includeDocs ? Docs.Get(ApiDocsPath) : null, options ?? DefaultTestGeneratorOptions, compilation ?? this.compilation, this.parseOptions))); diff --git a/test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs b/test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs index 95c20bfa..15644287 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs @@ -74,6 +74,15 @@ public void AvoidSafeHandles() Assert.Equal("HANDLE", Assert.IsType(friendlyOverload.ParameterList.Parameters[0].Type).Right.Identifier.ValueText); } + [Fact] + public void SafeHandleInWDK() + { + this.generator = this.CreateGenerator(DefaultTestGeneratorOptions); + Assert.True(this.generator.TryGenerate("OROpenHive", CancellationToken.None)); + this.CollectGeneratedCode(this.generator); + this.AssertNoDiagnostics(); + } + /// /// Verifies that MSIHANDLE is wrapped with a SafeHandle even though it is a 32-bit handle. /// This is safe because we never pass SafeHandle directly to extern methods, so we can fix the length of the parameter or return value. diff --git a/test/Microsoft.Windows.CsWin32.Tests/StructTests.cs b/test/Microsoft.Windows.CsWin32.Tests/StructTests.cs index 8ad8959a..88e98c13 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/StructTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/StructTests.cs @@ -178,6 +178,9 @@ public void FieldWithAssociatedEnum() [CombinatorialData] public void InterestingStructs( [CombinatorialValues( + "DRIVER_OBJECT", // has an inline array of delegates + "DEVICE_RELATIONS", // ends with an inline "flexible" array + "D3DHAL_CONTEXTCREATEDATA", // contains a field that is a pointer to a struct that is normally managed "WSD_EVENT")] // has a pointer field to a managed struct string name, bool allowMarshaling) diff --git a/version.json b/version.json index 9c252c11..f979d7e1 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.2-beta", + "version": "0.3-beta", "assemblyVersion": { "precision": "revision" },